"use strict";
(function() {
	Error.stackTraceLimit = Infinity;
	var $global, $module;
	if (typeof window !== "undefined") {
		$global = window;
	} else if (typeof self !== "undefined") {
		$global = self;
	} else if (typeof global !== "undefined") {
		$global = global;
		$global.require = require;
	} else {
		$global = this;
	}
	if ($global === undefined || $global.Array === undefined) {
		throw new Error("no global object found");
	}
	if (typeof module !== "undefined") {
		$module = module;
	}
	var $packages = {},
		$idCounter = 0;
	var $keys = function(m) {
		return m ? Object.keys(m) : [];
	};
	var $flushConsole = function() {};
	var $throwRuntimeError;
	var $throwNilPointerError = function() {
		$throwRuntimeError("invalid memory address or nil pointer dereference");
	};
	var $call = function(fn, rcvr, args) {
		return fn.apply(rcvr, args);
	};
	var $makeFunc = function(fn) {
		return function() {
			return $externalize(fn(this, new($sliceType($jsObjectPtr))($global.Array.prototype.slice.call(arguments, []))),
				$emptyInterface);
		};
	};
	var $unused = function(v) {};
	var $mapArray = function(array, f) {
		var newArray = new array.constructor(array.length);
		for (var i = 0; i < array.length; i++) {
			newArray[i] = f(array[i]);
		}
		return newArray;
	};
	var $methodVal = function(recv, name) {
		var vals = recv.$methodVals || {};
		recv.$methodVals = vals;
		var f = vals[name];
		if (f !== undefined) {
			return f;
		}
		var method = recv[name];
		f = function() {
			$stackDepthOffset--;
			try {
				return method.apply(recv, arguments);
			} finally {
				$stackDepthOffset++;
			}
		};
		vals[name] = f;
		return f;
	};
	var $methodExpr = function(typ, name) {
		var method = typ.prototype[name];
		if (method.$expr === undefined) {
			method.$expr = function() {
				$stackDepthOffset--;
				try {
					if (typ.wrapped) {
						arguments[0] = new typ(arguments[0]);
					}
					return Function.call.apply(method, arguments);
				} finally {
					$stackDepthOffset++;
				}
			};
		}
		return method.$expr;
	};
	var $ifaceMethodExprs = {};
	var $ifaceMethodExpr = function(name) {
		var expr = $ifaceMethodExprs["$" + name];
		if (expr === undefined) {
			expr = $ifaceMethodExprs["$" + name] = function() {
				$stackDepthOffset--;
				try {
					return Function.call.apply(arguments[0][name], arguments);
				} finally {
					$stackDepthOffset++;
				}
			};
		}
		return expr;
	};
	var $subslice = function(slice, low, high, max) {
		if (low < 0 || high < low || max < high || high > slice.$capacity || max > slice.$capacity) {
			$throwRuntimeError("slice bounds out of range");
		}
		var s = new slice.constructor(slice.$array);
		s.$offset = slice.$offset + low;
		s.$length = slice.$length - low;
		s.$capacity = slice.$capacity - low;
		if (high !== undefined) {
			s.$length = high - low;
		}
		if (max !== undefined) {
			s.$capacity = max - low;
		}
		return s;
	};
	var $substring = function(str, low, high) {
		if (low < 0 || high < low || high > str.length) {
			$throwRuntimeError("slice bounds out of range");
		}
		return str.substring(low, high);
	};
	var $sliceToArray = function(slice) {
		if (slice.$array.constructor !== Array) {
			return slice.$array.subarray(slice.$offset, slice.$offset + slice.$length);
		}
		return slice.$array.slice(slice.$offset, slice.$offset + slice.$length);
	};
	var $decodeRune = function(str, pos) {
		var c0 = str.charCodeAt(pos);
		if (c0 < 0x80) {
			return [c0, 1];
		}
		if (c0 !== c0 || c0 < 0xC0) {
			return [0xFFFD, 1];
		}
		var c1 = str.charCodeAt(pos + 1);
		if (c1 !== c1 || c1 < 0x80 || 0xC0 <= c1) {
			return [0xFFFD, 1];
		}
		if (c0 < 0xE0) {
			var r = (c0 & 0x1F) << 6 | (c1 & 0x3F);
			if (r <= 0x7F) {
				return [0xFFFD, 1];
			}
			return [r, 2];
		}
		var c2 = str.charCodeAt(pos + 2);
		if (c2 !== c2 || c2 < 0x80 || 0xC0 <= c2) {
			return [0xFFFD, 1];
		}
		if (c0 < 0xF0) {
			var r = (c0 & 0x0F) << 12 | (c1 & 0x3F) << 6 | (c2 & 0x3F);
			if (r <= 0x7FF) {
				return [0xFFFD, 1];
			}
			if (0xD800 <= r && r <= 0xDFFF) {
				return [0xFFFD, 1];
			}
			return [r, 3];
		}
		var c3 = str.charCodeAt(pos + 3);
		if (c3 !== c3 || c3 < 0x80 || 0xC0 <= c3) {
			return [0xFFFD, 1];
		}
		if (c0 < 0xF8) {
			var r = (c0 & 0x07) << 18 | (c1 & 0x3F) << 12 | (c2 & 0x3F) << 6 | (c3 & 0x3F);
			if (r <= 0xFFFF || 0x10FFFF < r) {
				return [0xFFFD, 1];
			}
			return [r, 4];
		}
		return [0xFFFD, 1];
	};
	var $encodeRune = function(r) {
		if (r < 0 || r > 0x10FFFF || (0xD800 <= r && r <= 0xDFFF)) {
			r = 0xFFFD;
		}
		if (r <= 0x7F) {
			return String.fromCharCode(r);
		}
		if (r <= 0x7FF) {
			return String.fromCharCode(0xC0 | r >> 6, 0x80 | (r & 0x3F));
		}
		if (r <= 0xFFFF) {
			return String.fromCharCode(0xE0 | r >> 12, 0x80 | (r >> 6 & 0x3F), 0x80 | (r & 0x3F));
		}
		return String.fromCharCode(0xF0 | r >> 18, 0x80 | (r >> 12 & 0x3F), 0x80 | (r >> 6 & 0x3F), 0x80 | (r & 0x3F));
	};
	var $stringToBytes = function(str) {
		var array = new Uint8Array(str.length);
		for (var i = 0; i < str.length; i++) {
			array[i] = str.charCodeAt(i);
		}
		return array;
	};
	var $bytesToString = function(slice) {
		if (slice.$length === 0) {
			return "";
		}
		var str = "";
		for (var i = 0; i < slice.$length; i += 10000) {
			str += String.fromCharCode.apply(undefined, slice.$array.subarray(slice.$offset + i, slice.$offset + Math.min(
				slice.$length, i + 10000)));
		}
		return str;
	};
	var $stringToRunes = function(str) {
		var array = new Int32Array(str.length);
		var rune, j = 0;
		for (var i = 0; i < str.length; i += rune[1], j++) {
			rune = $decodeRune(str, i);
			array[j] = rune[0];
		}
		return array.subarray(0, j);
	};
	var $runesToString = function(slice) {
		if (slice.$length === 0) {
			return "";
		}
		var str = "";
		for (var i = 0; i < slice.$length; i++) {
			str += $encodeRune(slice.$array[slice.$offset + i]);
		}
		return str;
	};
	var $copyString = function(dst, src) {
		var n = Math.min(src.length, dst.$length);
		for (var i = 0; i < n; i++) {
			dst.$array[dst.$offset + i] = src.charCodeAt(i);
		}
		return n;
	};
	var $copySlice = function(dst, src) {
		var n = Math.min(src.$length, dst.$length);
		$copyArray(dst.$array, src.$array, dst.$offset, src.$offset, n, dst.constructor.elem);
		return n;
	};
	var $copyArray = function(dst, src, dstOffset, srcOffset, n, elem) {
		if (n === 0 || (dst === src && dstOffset === srcOffset)) {
			return;
		}
		if (src.subarray) {
			dst.set(src.subarray(srcOffset, srcOffset + n), dstOffset);
			return;
		}
		switch (elem.kind) {
			case $kindArray:
			case $kindStruct:
				if (dst === src && dstOffset > srcOffset) {
					for (var i = n - 1; i >= 0; i--) {
						elem.copy(dst[dstOffset + i], src[srcOffset + i]);
					}
					return;
				}
				for (var i = 0; i < n; i++) {
					elem.copy(dst[dstOffset + i], src[srcOffset + i]);
				}
				return;
		}
		if (dst === src && dstOffset > srcOffset) {
			for (var i = n - 1; i >= 0; i--) {
				dst[dstOffset + i] = src[srcOffset + i];
			}
			return;
		}
		for (var i = 0; i < n; i++) {
			dst[dstOffset + i] = src[srcOffset + i];
		}
	};
	var $clone = function(src, type) {
		var clone = type.zero();
		type.copy(clone, src);
		return clone;
	};
	var $pointerOfStructConversion = function(obj, type) {
		if (obj.$proxies === undefined) {
			obj.$proxies = {};
			obj.$proxies[obj.constructor.string] = obj;
		}
		var proxy = obj.$proxies[type.string];
		if (proxy === undefined) {
			var properties = {};
			for (var i = 0; i < type.elem.fields.length; i++) {
				(function(fieldProp) {
					properties[fieldProp] = {
						get: function() {
							return obj[fieldProp];
						},
						set: function(value) {
							obj[fieldProp] = value;
						}
					};
				})(type.elem.fields[i].prop);
			}
			proxy = Object.create(type.prototype, properties);
			proxy.$val = proxy;
			obj.$proxies[type.string] = proxy;
			proxy.$proxies = obj.$proxies;
		}
		return proxy;
	};
	var $append = function(slice) {
		return $internalAppend(slice, arguments, 1, arguments.length - 1);
	};
	var $appendSlice = function(slice, toAppend) {
		if (toAppend.constructor === String) {
			var bytes = $stringToBytes(toAppend);
			return $internalAppend(slice, bytes, 0, bytes.length);
		}
		return $internalAppend(slice, toAppend.$array, toAppend.$offset, toAppend.$length);
	};
	var $internalAppend = function(slice, array, offset, length) {
		if (length === 0) {
			return slice;
		}
		var newArray = slice.$array;
		var newOffset = slice.$offset;
		var newLength = slice.$length + length;
		var newCapacity = slice.$capacity;
		if (newLength > newCapacity) {
			newOffset = 0;
			newCapacity = Math.max(newLength, slice.$capacity < 1024 ? slice.$capacity * 2 : Math.floor(slice.$capacity * 5 /
				4));
			if (slice.$array.constructor === Array) {
				newArray = slice.$array.slice(slice.$offset, slice.$offset + slice.$length);
				newArray.length = newCapacity;
				var zero = slice.constructor.elem.zero;
				for (var i = slice.$length; i < newCapacity; i++) {
					newArray[i] = zero();
				}
			} else {
				newArray = new slice.$array.constructor(newCapacity);
				newArray.set(slice.$array.subarray(slice.$offset, slice.$offset + slice.$length));
			}
		}
		$copyArray(newArray, array, newOffset + slice.$length, offset, length, slice.constructor.elem);
		var newSlice = new slice.constructor(newArray);
		newSlice.$offset = newOffset;
		newSlice.$length = newLength;
		newSlice.$capacity = newCapacity;
		return newSlice;
	};
	var $equal = function(a, b, type) {
		if (type === $jsObjectPtr) {
			return a === b;
		}
		switch (type.kind) {
			case $kindComplex64:
			case $kindComplex128:
				return a.$real === b.$real && a.$imag === b.$imag;
			case $kindInt64:
			case $kindUint64:
				return a.$high === b.$high && a.$low === b.$low;
			case $kindArray:
				if (a.length !== b.length) {
					return false;
				}
				for (var i = 0; i < a.length; i++) {
					if (!$equal(a[i], b[i], type.elem)) {
						return false;
					}
				}
				return true;
			case $kindStruct:
				for (var i = 0; i < type.fields.length; i++) {
					var f = type.fields[i];
					if (!$equal(a[f.prop], b[f.prop], f.typ)) {
						return false;
					}
				}
				return true;
			case $kindInterface:
				return $interfaceIsEqual(a, b);
			default:
				return a === b;
		}
	};
	var $interfaceIsEqual = function(a, b) {
		if (a === $ifaceNil || b === $ifaceNil) {
			return a === b;
		}
		if (a.constructor !== b.constructor) {
			return false;
		}
		if (a.constructor === $jsObjectPtr) {
			return a.object === b.object;
		}
		if (!a.constructor.comparable) {
			$throwRuntimeError("comparing uncomparable type " + a.constructor.string);
		}
		return $equal(a.$val, b.$val, a.constructor);
	};
	var $min = Math.min;
	var $mod = function(x, y) {
		return x % y;
	};
	var $parseInt = parseInt;
	var $parseFloat = function(f) {
		if (f !== undefined && f !== null && f.constructor === Number) {
			return f;
		}
		return parseFloat(f);
	};
	var $froundBuf = new Float32Array(1);
	var $fround = Math.fround || function(f) {
		$froundBuf[0] = f;
		return $froundBuf[0];
	};
	var $imul = Math.imul || function(a, b) {
		var ah = (a >>> 16) & 0xffff;
		var al = a & 0xffff;
		var bh = (b >>> 16) & 0xffff;
		var bl = b & 0xffff;
		return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) >> 0);
	};
	var $floatKey = function(f) {
		if (f !== f) {
			$idCounter++;
			return "NaN$" + $idCounter;
		}
		return String(f);
	};
	var $flatten64 = function(x) {
		return x.$high * 4294967296 + x.$low;
	};
	var $shiftLeft64 = function(x, y) {
		if (y === 0) {
			return x;
		}
		if (y < 32) {
			return new x.constructor(x.$high << y | x.$low >>> (32 - y), (x.$low << y) >>> 0);
		}
		if (y < 64) {
			return new x.constructor(x.$low << (y - 32), 0);
		}
		return new x.constructor(0, 0);
	};
	var $shiftRightInt64 = function(x, y) {
		if (y === 0) {
			return x;
		}
		if (y < 32) {
			return new x.constructor(x.$high >> y, (x.$low >>> y | x.$high << (32 - y)) >>> 0);
		}
		if (y < 64) {
			return new x.constructor(x.$high >> 31, (x.$high >> (y - 32)) >>> 0);
		}
		if (x.$high < 0) {
			return new x.constructor(-1, 4294967295);
		}
		return new x.constructor(0, 0);
	};
	var $shiftRightUint64 = function(x, y) {
		if (y === 0) {
			return x;
		}
		if (y < 32) {
			return new x.constructor(x.$high >>> y, (x.$low >>> y | x.$high << (32 - y)) >>> 0);
		}
		if (y < 64) {
			return new x.constructor(0, x.$high >>> (y - 32));
		}
		return new x.constructor(0, 0);
	};
	var $mul64 = function(x, y) {
		var high = 0,
			low = 0;
		if ((y.$low & 1) !== 0) {
			high = x.$high;
			low = x.$low;
		}
		for (var i = 1; i < 32; i++) {
			if ((y.$low & 1 << i) !== 0) {
				high += x.$high << i | x.$low >>> (32 - i);
				low += (x.$low << i) >>> 0;
			}
		}
		for (var i = 0; i < 32; i++) {
			if ((y.$high & 1 << i) !== 0) {
				high += x.$low << i;
			}
		}
		return new x.constructor(high, low);
	};
	var $div64 = function(x, y, returnRemainder) {
		if (y.$high === 0 && y.$low === 0) {
			$throwRuntimeError("integer divide by zero");
		}
		var s = 1;
		var rs = 1;
		var xHigh = x.$high;
		var xLow = x.$low;
		if (xHigh < 0) {
			s = -1;
			rs = -1;
			xHigh = -xHigh;
			if (xLow !== 0) {
				xHigh--;
				xLow = 4294967296 - xLow;
			}
		}
		var yHigh = y.$high;
		var yLow = y.$low;
		if (y.$high < 0) {
			s *= -1;
			yHigh = -yHigh;
			if (yLow !== 0) {
				yHigh--;
				yLow = 4294967296 - yLow;
			}
		}
		var high = 0,
			low = 0,
			n = 0;
		while (yHigh < 2147483648 && ((xHigh > yHigh) || (xHigh === yHigh && xLow > yLow))) {
			yHigh = (yHigh << 1 | yLow >>> 31) >>> 0;
			yLow = (yLow << 1) >>> 0;
			n++;
		}
		for (var i = 0; i <= n; i++) {
			high = high << 1 | low >>> 31;
			low = (low << 1) >>> 0;
			if ((xHigh > yHigh) || (xHigh === yHigh && xLow >= yLow)) {
				xHigh = xHigh - yHigh;
				xLow = xLow - yLow;
				if (xLow < 0) {
					xHigh--;
					xLow += 4294967296;
				}
				low++;
				if (low === 4294967296) {
					high++;
					low = 0;
				}
			}
			yLow = (yLow >>> 1 | yHigh << (32 - 1)) >>> 0;
			yHigh = yHigh >>> 1;
		}
		if (returnRemainder) {
			return new x.constructor(xHigh * rs, xLow * rs);
		}
		return new x.constructor(high * s, low * s);
	};
	var $divComplex = function(n, d) {
		var ninf = n.$real === Infinity || n.$real === -Infinity || n.$imag === Infinity || n.$imag === -Infinity;
		var dinf = d.$real === Infinity || d.$real === -Infinity || d.$imag === Infinity || d.$imag === -Infinity;
		var nnan = !ninf && (n.$real !== n.$real || n.$imag !== n.$imag);
		var dnan = !dinf && (d.$real !== d.$real || d.$imag !== d.$imag);
		if (nnan || dnan) {
			return new n.constructor(NaN, NaN);
		}
		if (ninf && !dinf) {
			return new n.constructor(Infinity, Infinity);
		}
		if (!ninf && dinf) {
			return new n.constructor(0, 0);
		}
		if (d.$real === 0 && d.$imag === 0) {
			if (n.$real === 0 && n.$imag === 0) {
				return new n.constructor(NaN, NaN);
			}
			return new n.constructor(Infinity, Infinity);
		}
		var a = Math.abs(d.$real);
		var b = Math.abs(d.$imag);
		if (a <= b) {
			var ratio = d.$real / d.$imag;
			var denom = d.$real * ratio + d.$imag;
			return new n.constructor((n.$real * ratio + n.$imag) / denom, (n.$imag * ratio - n.$real) / denom);
		}
		var ratio = d.$imag / d.$real;
		var denom = d.$imag * ratio + d.$real;
		return new n.constructor((n.$imag * ratio + n.$real) / denom, (n.$imag - n.$real * ratio) / denom);
	};
	var $kindBool = 1;
	var $kindInt = 2;
	var $kindInt8 = 3;
	var $kindInt16 = 4;
	var $kindInt32 = 5;
	var $kindInt64 = 6;
	var $kindUint = 7;
	var $kindUint8 = 8;
	var $kindUint16 = 9;
	var $kindUint32 = 10;
	var $kindUint64 = 11;
	var $kindUintptr = 12;
	var $kindFloat32 = 13;
	var $kindFloat64 = 14;
	var $kindComplex64 = 15;
	var $kindComplex128 = 16;
	var $kindArray = 17;
	var $kindChan = 18;
	var $kindFunc = 19;
	var $kindInterface = 20;
	var $kindMap = 21;
	var $kindPtr = 22;
	var $kindSlice = 23;
	var $kindString = 24;
	var $kindStruct = 25;
	var $kindUnsafePointer = 26;
	var $methodSynthesizers = [];
	var $addMethodSynthesizer = function(f) {
		if ($methodSynthesizers === null) {
			f();
			return;
		}
		$methodSynthesizers.push(f);
	};
	var $synthesizeMethods = function() {
		$methodSynthesizers.forEach(function(f) {
			f();
		});
		$methodSynthesizers = null;
	};
	var $ifaceKeyFor = function(x) {
		if (x === $ifaceNil) {
			return 'nil';
		}
		var c = x.constructor;
		return c.string + '$' + c.keyFor(x.$val);
	};
	var $identity = function(x) {
		return x;
	};
	var $typeIDCounter = 0;
	var $idKey = function(x) {
		if (x.$id === undefined) {
			$idCounter++;
			x.$id = $idCounter;
		}
		return String(x.$id);
	};
	var $newType = function(size, kind, string, named, pkg, exported, constructor) {
		var typ;
		switch (kind) {
			case $kindBool:
			case $kindInt:
			case $kindInt8:
			case $kindInt16:
			case $kindInt32:
			case $kindUint:
			case $kindUint8:
			case $kindUint16:
			case $kindUint32:
			case $kindUintptr:
			case $kindUnsafePointer:
				typ = function(v) {
					this.$val = v;
				};
				typ.wrapped = true;
				typ.keyFor = $identity;
				break;
			case $kindString:
				typ = function(v) {
					this.$val = v;
				};
				typ.wrapped = true;
				typ.keyFor = function(x) {
					return "$" + x;
				};
				break;
			case $kindFloat32:
			case $kindFloat64:
				typ = function(v) {
					this.$val = v;
				};
				typ.wrapped = true;
				typ.keyFor = function(x) {
					return $floatKey(x);
				};
				break;
			case $kindInt64:
				typ = function(high, low) {
					this.$high = (high + Math.floor(Math.ceil(low) / 4294967296)) >> 0;
					this.$low = low >>> 0;
					this.$val = this;
				};
				typ.keyFor = function(x) {
					return x.$high + "$" + x.$low;
				};
				break;
			case $kindUint64:
				typ = function(high, low) {
					this.$high = (high + Math.floor(Math.ceil(low) / 4294967296)) >>> 0;
					this.$low = low >>> 0;
					this.$val = this;
				};
				typ.keyFor = function(x) {
					return x.$high + "$" + x.$low;
				};
				break;
			case $kindComplex64:
				typ = function(real, imag) {
					this.$real = $fround(real);
					this.$imag = $fround(imag);
					this.$val = this;
				};
				typ.keyFor = function(x) {
					return x.$real + "$" + x.$imag;
				};
				break;
			case $kindComplex128:
				typ = function(real, imag) {
					this.$real = real;
					this.$imag = imag;
					this.$val = this;
				};
				typ.keyFor = function(x) {
					return x.$real + "$" + x.$imag;
				};
				break;
			case $kindArray:
				typ = function(v) {
					this.$val = v;
				};
				typ.wrapped = true;
				typ.ptr = $newType(4, $kindPtr, "*" + string, false, "", false, function(array) {
					this.$get = function() {
						return array;
					};
					this.$set = function(v) {
						typ.copy(this, v);
					};
					this.$val = array;
				});
				typ.init = function(elem, len) {
					typ.elem = elem;
					typ.len = len;
					typ.comparable = elem.comparable;
					typ.keyFor = function(x) {
						return Array.prototype.join.call($mapArray(x, function(e) {
							return String(elem.keyFor(e)).replace(/\\/g, "\\\\").replace(/\$/g, "\\$");
						}), "$");
					};
					typ.copy = function(dst, src) {
						$copyArray(dst, src, 0, 0, src.length, elem);
					};
					typ.ptr.init(typ);
					Object.defineProperty(typ.ptr.nil, "nilCheck", {
						get: $throwNilPointerError
					});
				};
				break;
			case $kindChan:
				typ = function(v) {
					this.$val = v;
				};
				typ.wrapped = true;
				typ.keyFor = $idKey;
				typ.init = function(elem, sendOnly, recvOnly) {
					typ.elem = elem;
					typ.sendOnly = sendOnly;
					typ.recvOnly = recvOnly;
				};
				break;
			case $kindFunc:
				typ = function(v) {
					this.$val = v;
				};
				typ.wrapped = true;
				typ.init = function(params, results, variadic) {
					typ.params = params;
					typ.results = results;
					typ.variadic = variadic;
					typ.comparable = false;
				};
				break;
			case $kindInterface:
				typ = {
					implementedBy: {},
					missingMethodFor: {}
				};
				typ.keyFor = $ifaceKeyFor;
				typ.init = function(methods) {
					typ.methods = methods;
					methods.forEach(function(m) {
						$ifaceNil[m.prop] = $throwNilPointerError;
					});
				};
				break;
			case $kindMap:
				typ = function(v) {
					this.$val = v;
				};
				typ.wrapped = true;
				typ.init = function(key, elem) {
					typ.key = key;
					typ.elem = elem;
					typ.comparable = false;
				};
				break;
			case $kindPtr:
				typ = constructor || function(getter, setter, target) {
					this.$get = getter;
					this.$set = setter;
					this.$target = target;
					this.$val = this;
				};
				typ.keyFor = $idKey;
				typ.init = function(elem) {
					typ.elem = elem;
					typ.wrapped = (elem.kind === $kindArray);
					typ.nil = new typ($throwNilPointerError, $throwNilPointerError);
				};
				break;
			case $kindSlice:
				typ = function(array) {
					if (array.constructor !== typ.nativeArray) {
						array = new typ.nativeArray(array);
					}
					this.$array = array;
					this.$offset = 0;
					this.$length = array.length;
					this.$capacity = array.length;
					this.$val = this;
				};
				typ.init = function(elem) {
					typ.elem = elem;
					typ.comparable = false;
					typ.nativeArray = $nativeArray(elem.kind);
					typ.nil = new typ([]);
				};
				break;
			case $kindStruct:
				typ = function(v) {
					this.$val = v;
				};
				typ.wrapped = true;
				typ.ptr = $newType(4, $kindPtr, "*" + string, false, pkg, exported, constructor);
				typ.ptr.elem = typ;
				typ.ptr.prototype.$get = function() {
					return this;
				};
				typ.ptr.prototype.$set = function(v) {
					typ.copy(this, v);
				};
				typ.init = function(pkgPath, fields) {
					typ.pkgPath = pkgPath;
					typ.fields = fields;
					fields.forEach(function(f) {
						if (!f.typ.comparable) {
							typ.comparable = false;
						}
					});
					typ.keyFor = function(x) {
						var val = x.$val;
						return $mapArray(fields, function(f) {
							return String(f.typ.keyFor(val[f.prop])).replace(/\\/g, "\\\\").replace(/\$/g, "\\$");
						}).join("$");
					};
					typ.copy = function(dst, src) {
						for (var i = 0; i < fields.length; i++) {
							var f = fields[i];
							switch (f.typ.kind) {
								case $kindArray:
								case $kindStruct:
									f.typ.copy(dst[f.prop], src[f.prop]);
									continue;
								default:
									dst[f.prop] = src[f.prop];
									continue;
							}
						}
					};
					var properties = {};
					fields.forEach(function(f) {
						properties[f.prop] = {
							get: $throwNilPointerError,
							set: $throwNilPointerError
						};
					});
					typ.ptr.nil = Object.create(constructor.prototype, properties);
					typ.ptr.nil.$val = typ.ptr.nil;
					$addMethodSynthesizer(function() {
						var synthesizeMethod = function(target, m, f) {
							if (target.prototype[m.prop] !== undefined) {
								return;
							}
							target.prototype[m.prop] = function() {
								var v = this.$val[f.prop];
								if (f.typ === $jsObjectPtr) {
									v = new $jsObjectPtr(v);
								}
								if (v.$val === undefined) {
									v = new f.typ(v);
								}
								return v[m.prop].apply(v, arguments);
							};
						};
						fields.forEach(function(f) {
							if (f.anonymous) {
								$methodSet(f.typ).forEach(function(m) {
									synthesizeMethod(typ, m, f);
									synthesizeMethod(typ.ptr, m, f);
								});
								$methodSet($ptrType(f.typ)).forEach(function(m) {
									synthesizeMethod(typ.ptr, m, f);
								});
							}
						});
					});
				};
				break;
			default:
				$panic(new $String("invalid kind: " + kind));
		}
		switch (kind) {
			case $kindBool:
			case $kindMap:
				typ.zero = function() {
					return false;
				};
				break;
			case $kindInt:
			case $kindInt8:
			case $kindInt16:
			case $kindInt32:
			case $kindUint:
			case $kindUint8:
			case $kindUint16:
			case $kindUint32:
			case $kindUintptr:
			case $kindUnsafePointer:
			case $kindFloat32:
			case $kindFloat64:
				typ.zero = function() {
					return 0;
				};
				break;
			case $kindString:
				typ.zero = function() {
					return "";
				};
				break;
			case $kindInt64:
			case $kindUint64:
			case $kindComplex64:
			case $kindComplex128:
				var zero = new typ(0, 0);
				typ.zero = function() {
					return zero;
				};
				break;
			case $kindPtr:
			case $kindSlice:
				typ.zero = function() {
					return typ.nil;
				};
				break;
			case $kindChan:
				typ.zero = function() {
					return $chanNil;
				};
				break;
			case $kindFunc:
				typ.zero = function() {
					return $throwNilPointerError;
				};
				break;
			case $kindInterface:
				typ.zero = function() {
					return $ifaceNil;
				};
				break;
			case $kindArray:
				typ.zero = function() {
					var arrayClass = $nativeArray(typ.elem.kind);
					if (arrayClass !== Array) {
						return new arrayClass(typ.len);
					}
					var array = new Array(typ.len);
					for (var i = 0; i < typ.len; i++) {
						array[i] = typ.elem.zero();
					}
					return array;
				};
				break;
			case $kindStruct:
				typ.zero = function() {
					return new typ.ptr();
				};
				break;
			default:
				$panic(new $String("invalid kind: " + kind));
		}
		typ.id = $typeIDCounter;
		$typeIDCounter++;
		typ.size = size;
		typ.kind = kind;
		typ.string = string;
		typ.named = named;
		typ.pkg = pkg;
		typ.exported = exported;
		typ.methods = [];
		typ.methodSetCache = null;
		typ.comparable = true;
		return typ;
	};
	var $methodSet = function(typ) {
		if (typ.methodSetCache !== null) {
			return typ.methodSetCache;
		}
		var base = {};
		var isPtr = (typ.kind === $kindPtr);
		if (isPtr && typ.elem.kind === $kindInterface) {
			typ.methodSetCache = [];
			return [];
		}
		var current = [{
			typ: isPtr ? typ.elem : typ,
			indirect: isPtr
		}];
		var seen = {};
		while (current.length > 0) {
			var next = [];
			var mset = [];
			current.forEach(function(e) {
				if (seen[e.typ.string]) {
					return;
				}
				seen[e.typ.string] = true;
				if (e.typ.named) {
					mset = mset.concat(e.typ.methods);
					if (e.indirect) {
						mset = mset.concat($ptrType(e.typ).methods);
					}
				}
				switch (e.typ.kind) {
					case $kindStruct:
						e.typ.fields.forEach(function(f) {
							if (f.anonymous) {
								var fTyp = f.typ;
								var fIsPtr = (fTyp.kind === $kindPtr);
								next.push({
									typ: fIsPtr ? fTyp.elem : fTyp,
									indirect: e.indirect || fIsPtr
								});
							}
						});
						break;
					case $kindInterface:
						mset = mset.concat(e.typ.methods);
						break;
				}
			});
			mset.forEach(function(m) {
				if (base[m.name] === undefined) {
					base[m.name] = m;
				}
			});
			current = next;
		}
		typ.methodSetCache = [];
		Object.keys(base).sort().forEach(function(name) {
			typ.methodSetCache.push(base[name]);
		});
		return typ.methodSetCache;
	};
	var $Bool = $newType(1, $kindBool, "bool", true, "", false, null);
	var $Int = $newType(4, $kindInt, "int", true, "", false, null);
	var $Int8 = $newType(1, $kindInt8, "int8", true, "", false, null);
	var $Int16 = $newType(2, $kindInt16, "int16", true, "", false, null);
	var $Int32 = $newType(4, $kindInt32, "int32", true, "", false, null);
	var $Int64 = $newType(8, $kindInt64, "int64", true, "", false, null);
	var $Uint = $newType(4, $kindUint, "uint", true, "", false, null);
	var $Uint8 = $newType(1, $kindUint8, "uint8", true, "", false, null);
	var $Uint16 = $newType(2, $kindUint16, "uint16", true, "", false, null);
	var $Uint32 = $newType(4, $kindUint32, "uint32", true, "", false, null);
	var $Uint64 = $newType(8, $kindUint64, "uint64", true, "", false, null);
	var $Uintptr = $newType(4, $kindUintptr, "uintptr", true, "", false, null);
	var $Float32 = $newType(4, $kindFloat32, "float32", true, "", false, null);
	var $Float64 = $newType(8, $kindFloat64, "float64", true, "", false, null);
	var $Complex64 = $newType(8, $kindComplex64, "complex64", true, "", false, null);
	var $Complex128 = $newType(16, $kindComplex128, "complex128", true, "", false, null);
	var $String = $newType(8, $kindString, "string", true, "", false, null);
	var $UnsafePointer = $newType(4, $kindUnsafePointer, "unsafe.Pointer", true, "", false, null);
	var $nativeArray = function(elemKind) {
		switch (elemKind) {
			case $kindInt:
				return Int32Array;
			case $kindInt8:
				return Int8Array;
			case $kindInt16:
				return Int16Array;
			case $kindInt32:
				return Int32Array;
			case $kindUint:
				return Uint32Array;
			case $kindUint8:
				return Uint8Array;
			case $kindUint16:
				return Uint16Array;
			case $kindUint32:
				return Uint32Array;
			case $kindUintptr:
				return Uint32Array;
			case $kindFloat32:
				return Float32Array;
			case $kindFloat64:
				return Float64Array;
			default:
				return Array;
		}
	};
	var $toNativeArray = function(elemKind, array) {
		var nativeArray = $nativeArray(elemKind);
		if (nativeArray === Array) {
			return array;
		}
		return new nativeArray(array);
	};
	var $arrayTypes = {};
	var $arrayType = function(elem, len) {
		var typeKey = elem.id + "$" + len;
		var typ = $arrayTypes[typeKey];
		if (typ === undefined) {
			typ = $newType(12, $kindArray, "[" + len + "]" + elem.string, false, "", false, null);
			$arrayTypes[typeKey] = typ;
			typ.init(elem, len);
		}
		return typ;
	};
	var $chanType = function(elem, sendOnly, recvOnly) {
		var string = (recvOnly ? "<-" : "") + "chan" + (sendOnly ? "<- " : " ") + elem.string;
		var field = sendOnly ? "SendChan" : (recvOnly ? "RecvChan" : "Chan");
		var typ = elem[field];
		if (typ === undefined) {
			typ = $newType(4, $kindChan, string, false, "", false, null);
			elem[field] = typ;
			typ.init(elem, sendOnly, recvOnly);
		}
		return typ;
	};
	var $Chan = function(elem, capacity) {
		if (capacity < 0 || capacity > 2147483647) {
			$throwRuntimeError("makechan: size out of range");
		}
		this.$elem = elem;
		this.$capacity = capacity;
		this.$buffer = [];
		this.$sendQueue = [];
		this.$recvQueue = [];
		this.$closed = false;
	};
	var $chanNil = new $Chan(null, 0);
	$chanNil.$sendQueue = $chanNil.$recvQueue = {
		length: 0,
		push: function() {},
		shift: function() {
			return undefined;
		},
		indexOf: function() {
			return -1;
		}
	};
	var $funcTypes = {};
	var $funcType = function(params, results, variadic) {
		var typeKey = $mapArray(params, function(p) {
			return p.id;
		}).join(",") + "$" + $mapArray(results, function(r) {
			return r.id;
		}).join(",") + "$" + variadic;
		var typ = $funcTypes[typeKey];
		if (typ === undefined) {
			var paramTypes = $mapArray(params, function(p) {
				return p.string;
			});
			if (variadic) {
				paramTypes[paramTypes.length - 1] = "..." + paramTypes[paramTypes.length - 1].substr(2);
			}
			var string = "func(" + paramTypes.join(", ") + ")";
			if (results.length === 1) {
				string += " " + results[0].string;
			} else if (results.length > 1) {
				string += " (" + $mapArray(results, function(r) {
					return r.string;
				}).join(", ") + ")";
			}
			typ = $newType(4, $kindFunc, string, false, "", false, null);
			$funcTypes[typeKey] = typ;
			typ.init(params, results, variadic);
		}
		return typ;
	};
	var $interfaceTypes = {};
	var $interfaceType = function(methods) {
		var typeKey = $mapArray(methods, function(m) {
			return m.pkg + "," + m.name + "," + m.typ.id;
		}).join("$");
		var typ = $interfaceTypes[typeKey];
		if (typ === undefined) {
			var string = "interface {}";
			if (methods.length !== 0) {
				string = "interface { " + $mapArray(methods, function(m) {
					return (m.pkg !== "" ? m.pkg + "." : "") + m.name + m.typ.string.substr(4);
				}).join("; ") + " }";
			}
			typ = $newType(8, $kindInterface, string, false, "", false, null);
			$interfaceTypes[typeKey] = typ;
			typ.init(methods);
		}
		return typ;
	};
	var $emptyInterface = $interfaceType([]);
	var $ifaceNil = {};
	var $error = $newType(8, $kindInterface, "error", true, "", false, null);
	$error.init([{
		prop: "Error",
		name: "Error",
		pkg: "",
		typ: $funcType([], [$String], false)
	}]);
	var $mapTypes = {};
	var $mapType = function(key, elem) {
		var typeKey = key.id + "$" + elem.id;
		var typ = $mapTypes[typeKey];
		if (typ === undefined) {
			typ = $newType(4, $kindMap, "map[" + key.string + "]" + elem.string, false, "", false, null);
			$mapTypes[typeKey] = typ;
			typ.init(key, elem);
		}
		return typ;
	};
	var $makeMap = function(keyForFunc, entries) {
		var m = {};
		for (var i = 0; i < entries.length; i++) {
			var e = entries[i];
			m[keyForFunc(e.k)] = e;
		}
		return m;
	};
	var $ptrType = function(elem) {
		var typ = elem.ptr;
		if (typ === undefined) {
			typ = $newType(4, $kindPtr, "*" + elem.string, false, "", elem.exported, null);
			elem.ptr = typ;
			typ.init(elem);
		}
		return typ;
	};
	var $newDataPointer = function(data, constructor) {
		if (constructor.elem.kind === $kindStruct) {
			return data;
		}
		return new constructor(function() {
			return data;
		}, function(v) {
			data = v;
		});
	};
	var $indexPtr = function(array, index, constructor) {
		array.$ptr = array.$ptr || {};
		return array.$ptr[index] || (array.$ptr[index] = new constructor(function() {
			return array[index];
		}, function(v) {
			array[index] = v;
		}));
	};
	var $sliceType = function(elem) {
		var typ = elem.slice;
		if (typ === undefined) {
			typ = $newType(12, $kindSlice, "[]" + elem.string, false, "", false, null);
			elem.slice = typ;
			typ.init(elem);
		}
		return typ;
	};
	var $makeSlice = function(typ, length, capacity) {
		capacity = capacity || length;
		if (length < 0 || length > 2147483647) {
			$throwRuntimeError("makeslice: len out of range");
		}
		if (capacity < 0 || capacity < length || capacity > 2147483647) {
			$throwRuntimeError("makeslice: cap out of range");
		}
		var array = new typ.nativeArray(capacity);
		if (typ.nativeArray === Array) {
			for (var i = 0; i < capacity; i++) {
				array[i] = typ.elem.zero();
			}
		}
		var slice = new typ(array);
		slice.$length = length;
		return slice;
	};
	var $structTypes = {};
	var $structType = function(pkgPath, fields) {
		var typeKey = $mapArray(fields, function(f) {
			return f.name + "," + f.typ.id + "," + f.tag;
		}).join("$");
		var typ = $structTypes[typeKey];
		if (typ === undefined) {
			var string = "struct { " + $mapArray(fields, function(f) {
				return f.name + " " + f.typ.string + (f.tag !== "" ? (" \"" + f.tag.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") +
					"\"") : "");
			}).join("; ") + " }";
			if (fields.length === 0) {
				string = "struct {}";
			}
			typ = $newType(0, $kindStruct, string, false, "", false, function() {
				this.$val = this;
				for (var i = 0; i < fields.length; i++) {
					var f = fields[i];
					var arg = arguments[i];
					this[f.prop] = arg !== undefined ? arg : f.typ.zero();
				}
			});
			$structTypes[typeKey] = typ;
			typ.init(pkgPath, fields);
		}
		return typ;
	};
	var $assertType = function(value, type, returnTuple) {
		var isInterface = (type.kind === $kindInterface),
			ok, missingMethod = "";
		if (value === $ifaceNil) {
			ok = false;
		} else if (!isInterface) {
			ok = value.constructor === type;
		} else {
			var valueTypeString = value.constructor.string;
			ok = type.implementedBy[valueTypeString];
			if (ok === undefined) {
				ok = true;
				var valueMethodSet = $methodSet(value.constructor);
				var interfaceMethods = type.methods;
				for (var i = 0; i < interfaceMethods.length; i++) {
					var tm = interfaceMethods[i];
					var found = false;
					for (var j = 0; j < valueMethodSet.length; j++) {
						var vm = valueMethodSet[j];
						if (vm.name === tm.name && vm.pkg === tm.pkg && vm.typ === tm.typ) {
							found = true;
							break;
						}
					}
					if (!found) {
						ok = false;
						type.missingMethodFor[valueTypeString] = tm.name;
						break;
					}
				}
				type.implementedBy[valueTypeString] = ok;
			}
			if (!ok) {
				missingMethod = type.missingMethodFor[valueTypeString];
			}
		}
		if (!ok) {
			if (returnTuple) {
				return [type.zero(), false];
			}
			$panic(new $packages["runtime"].TypeAssertionError.ptr("", (value === $ifaceNil ? "" : value.constructor.string),
				type.string, missingMethod));
		}
		if (!isInterface) {
			value = value.$val;
		}
		if (type === $jsObjectPtr) {
			value = value.object;
		}
		return returnTuple ? [value, true] : value;
	};
	var $stackDepthOffset = 0;
	var $getStackDepth = function() {
		var err = new Error();
		if (err.stack === undefined) {
			return undefined;
		}
		return $stackDepthOffset + err.stack.split("\n").length;
	};
	var $panicStackDepth = null,
		$panicValue;
	var $callDeferred = function(deferred, jsErr, fromPanic) {
		if (!fromPanic && deferred !== null && deferred.index >= $curGoroutine.deferStack.length) {
			throw jsErr;
		}
		if (jsErr !== null) {
			var newErr = null;
			try {
				$curGoroutine.deferStack.push(deferred);
				$panic(new $jsErrorPtr(jsErr));
			} catch (err) {
				newErr = err;
			}
			$curGoroutine.deferStack.pop();
			$callDeferred(deferred, newErr);
			return;
		}
		if ($curGoroutine.asleep) {
			return;
		}
		$stackDepthOffset--;
		var outerPanicStackDepth = $panicStackDepth;
		var outerPanicValue = $panicValue;
		var localPanicValue = $curGoroutine.panicStack.pop();
		if (localPanicValue !== undefined) {
			$panicStackDepth = $getStackDepth();
			$panicValue = localPanicValue;
		}
		try {
			while (true) {
				if (deferred === null) {
					deferred = $curGoroutine.deferStack[$curGoroutine.deferStack.length - 1];
					if (deferred === undefined) {
						$panicStackDepth = null;
						if (localPanicValue.Object instanceof Error) {
							throw localPanicValue.Object;
						}
						var msg;
						if (localPanicValue.constructor === $String) {
							msg = localPanicValue.$val;
						} else if (localPanicValue.Error !== undefined) {
							msg = localPanicValue.Error();
						} else if (localPanicValue.String !== undefined) {
							msg = localPanicValue.String();
						} else {
							msg = localPanicValue;
						}
						throw new Error(msg);
					}
				}
				var call = deferred.pop();
				if (call === undefined) {
					$curGoroutine.deferStack.pop();
					if (localPanicValue !== undefined) {
						deferred = null;
						continue;
					}
					return;
				}
				var r = call[0].apply(call[2], call[1]);
				if (r && r.$blk !== undefined) {
					deferred.push([r.$blk, [], r]);
					if (fromPanic) {
						throw null;
					}
					return;
				}
				if (localPanicValue !== undefined && $panicStackDepth === null) {
					throw null;
				}
			}
		} finally {
			if (localPanicValue !== undefined) {
				if ($panicStackDepth !== null) {
					$curGoroutine.panicStack.push(localPanicValue);
				}
				$panicStackDepth = outerPanicStackDepth;
				$panicValue = outerPanicValue;
			}
			$stackDepthOffset++;
		}
	};
	var $panic = function(value) {
		$curGoroutine.panicStack.push(value);
		$callDeferred(null, null, true);
	};
	var $recover = function() {
		if ($panicStackDepth === null || ($panicStackDepth !== undefined && $panicStackDepth !== $getStackDepth() - 2)) {
			return $ifaceNil;
		}
		$panicStackDepth = null;
		return $panicValue;
	};
	var $throw = function(err) {
		throw err;
	};
	var $noGoroutine = {
		asleep: false,
		exit: false,
		deferStack: [],
		panicStack: []
	};
	var $curGoroutine = $noGoroutine,
		$totalGoroutines = 0,
		$awakeGoroutines = 0,
		$checkForDeadlock = true;
	var $mainFinished = false;
	var $go = function(fun, args) {
		$totalGoroutines++;
		$awakeGoroutines++;
		var $goroutine = function() {
			try {
				$curGoroutine = $goroutine;
				var r = fun.apply(undefined, args);
				if (r && r.$blk !== undefined) {
					fun = function() {
						return r.$blk();
					};
					args = [];
					return;
				}
				$goroutine.exit = true;
			} catch (err) {
				if (!$goroutine.exit) {
					throw err;
				}
			} finally {
				$curGoroutine = $noGoroutine;
				if ($goroutine.exit) {
					$totalGoroutines--;
					$goroutine.asleep = true;
				}
				if ($goroutine.asleep) {
					$awakeGoroutines--;
					if (!$mainFinished && $awakeGoroutines === 0 && $checkForDeadlock) {
						console.error("fatal error: all goroutines are asleep - deadlock!");
						if ($global.process !== undefined) {
							$global.process.exit(2);
						}
					}
				}
			}
		};
		$goroutine.asleep = false;
		$goroutine.exit = false;
		$goroutine.deferStack = [];
		$goroutine.panicStack = [];
		$schedule($goroutine);
	};
	var $scheduled = [];
	var $runScheduled = function() {
		try {
			var r;
			while ((r = $scheduled.shift()) !== undefined) {
				r();
			}
		} finally {
			if ($scheduled.length > 0) {
				setTimeout($runScheduled, 0);
			}
		}
	};
	var $schedule = function(goroutine) {
		if (goroutine.asleep) {
			goroutine.asleep = false;
			$awakeGoroutines++;
		}
		$scheduled.push(goroutine);
		if ($curGoroutine === $noGoroutine) {
			$runScheduled();
		}
	};
	var $setTimeout = function(f, t) {
		$awakeGoroutines++;
		return setTimeout(function() {
			$awakeGoroutines--;
			f();
		}, t);
	};
	var $block = function() {
		if ($curGoroutine === $noGoroutine) {
			$throwRuntimeError("cannot block in JavaScript callback, fix by wrapping code in goroutine");
		}
		$curGoroutine.asleep = true;
	};
	var $send = function(chan, value) {
		if (chan.$closed) {
			$throwRuntimeError("send on closed channel");
		}
		var queuedRecv = chan.$recvQueue.shift();
		if (queuedRecv !== undefined) {
			queuedRecv([value, true]);
			return;
		}
		if (chan.$buffer.length < chan.$capacity) {
			chan.$buffer.push(value);
			return;
		}
		var thisGoroutine = $curGoroutine;
		var closedDuringSend;
		chan.$sendQueue.push(function(closed) {
			closedDuringSend = closed;
			$schedule(thisGoroutine);
			return value;
		});
		$block();
		return {
			$blk: function() {
				if (closedDuringSend) {
					$throwRuntimeError("send on closed channel");
				}
			}
		};
	};
	var $recv = function(chan) {
		var queuedSend = chan.$sendQueue.shift();
		if (queuedSend !== undefined) {
			chan.$buffer.push(queuedSend(false));
		}
		var bufferedValue = chan.$buffer.shift();
		if (bufferedValue !== undefined) {
			return [bufferedValue, true];
		}
		if (chan.$closed) {
			return [chan.$elem.zero(), false];
		}
		var thisGoroutine = $curGoroutine;
		var f = {
			$blk: function() {
				return this.value;
			}
		};
		var queueEntry = function(v) {
			f.value = v;
			$schedule(thisGoroutine);
		};
		chan.$recvQueue.push(queueEntry);
		$block();
		return f;
	};
	var $close = function(chan) {
		if (chan.$closed) {
			$throwRuntimeError("close of closed channel");
		}
		chan.$closed = true;
		while (true) {
			var queuedSend = chan.$sendQueue.shift();
			if (queuedSend === undefined) {
				break;
			}
			queuedSend(true);
		}
		while (true) {
			var queuedRecv = chan.$recvQueue.shift();
			if (queuedRecv === undefined) {
				break;
			}
			queuedRecv([chan.$elem.zero(), false]);
		}
	};
	var $select = function(comms) {
		var ready = [];
		var selection = -1;
		for (var i = 0; i < comms.length; i++) {
			var comm = comms[i];
			var chan = comm[0];
			switch (comm.length) {
				case 0:
					selection = i;
					break;
				case 1:
					if (chan.$sendQueue.length !== 0 || chan.$buffer.length !== 0 || chan.$closed) {
						ready.push(i);
					}
					break;
				case 2:
					if (chan.$closed) {
						$throwRuntimeError("send on closed channel");
					}
					if (chan.$recvQueue.length !== 0 || chan.$buffer.length < chan.$capacity) {
						ready.push(i);
					}
					break;
			}
		}
		if (ready.length !== 0) {
			selection = ready[Math.floor(Math.random() * ready.length)];
		}
		if (selection !== -1) {
			var comm = comms[selection];
			switch (comm.length) {
				case 0:
					return [selection];
				case 1:
					return [selection, $recv(comm[0])];
				case 2:
					$send(comm[0], comm[1]);
					return [selection];
			}
		}
		var entries = [];
		var thisGoroutine = $curGoroutine;
		var f = {
			$blk: function() {
				return this.selection;
			}
		};
		var removeFromQueues = function() {
			for (var i = 0; i < entries.length; i++) {
				var entry = entries[i];
				var queue = entry[0];
				var index = queue.indexOf(entry[1]);
				if (index !== -1) {
					queue.splice(index, 1);
				}
			}
		};
		for (var i = 0; i < comms.length; i++) {
			(function(i) {
				var comm = comms[i];
				switch (comm.length) {
					case 1:
						var queueEntry = function(value) {
							f.selection = [i, value];
							removeFromQueues();
							$schedule(thisGoroutine);
						};
						entries.push([comm[0].$recvQueue, queueEntry]);
						comm[0].$recvQueue.push(queueEntry);
						break;
					case 2:
						var queueEntry = function() {
							if (comm[0].$closed) {
								$throwRuntimeError("send on closed channel");
							}
							f.selection = [i];
							removeFromQueues();
							$schedule(thisGoroutine);
							return comm[1];
						};
						entries.push([comm[0].$sendQueue, queueEntry]);
						comm[0].$sendQueue.push(queueEntry);
						break;
				}
			})(i);
		}
		$block();
		return f;
	};
	var $jsObjectPtr, $jsErrorPtr;
	var $needsExternalization = function(t) {
		switch (t.kind) {
			case $kindBool:
			case $kindInt:
			case $kindInt8:
			case $kindInt16:
			case $kindInt32:
			case $kindUint:
			case $kindUint8:
			case $kindUint16:
			case $kindUint32:
			case $kindUintptr:
			case $kindFloat32:
			case $kindFloat64:
				return false;
			default:
				return t !== $jsObjectPtr;
		}
	};
	var $externalize = function(v, t) {
		if (t === $jsObjectPtr) {
			return v;
		}
		switch (t.kind) {
			case $kindBool:
			case $kindInt:
			case $kindInt8:
			case $kindInt16:
			case $kindInt32:
			case $kindUint:
			case $kindUint8:
			case $kindUint16:
			case $kindUint32:
			case $kindUintptr:
			case $kindFloat32:
			case $kindFloat64:
				return v;
			case $kindInt64:
			case $kindUint64:
				return $flatten64(v);
			case $kindArray:
				if ($needsExternalization(t.elem)) {
					return $mapArray(v, function(e) {
						return $externalize(e, t.elem);
					});
				}
				return v;
			case $kindFunc:
				return $externalizeFunction(v, t, false);
			case $kindInterface:
				if (v === $ifaceNil) {
					return null;
				}
				if (v.constructor === $jsObjectPtr) {
					return v.$val.object;
				}
				return $externalize(v.$val, v.constructor);
			case $kindMap:
				var m = {};
				var keys = $keys(v);
				for (var i = 0; i < keys.length; i++) {
					var entry = v[keys[i]];
					m[$externalize(entry.k, t.key)] = $externalize(entry.v, t.elem);
				}
				return m;
			case $kindPtr:
				if (v === t.nil) {
					return null;
				}
				return $externalize(v.$get(), t.elem);
			case $kindSlice:
				if ($needsExternalization(t.elem)) {
					return $mapArray($sliceToArray(v), function(e) {
						return $externalize(e, t.elem);
					});
				}
				return $sliceToArray(v);
			case $kindString:
				if ($isASCII(v)) {
					return v;
				}
				var s = "",
					r;
				for (var i = 0; i < v.length; i += r[1]) {
					r = $decodeRune(v, i);
					var c = r[0];
					if (c > 0xFFFF) {
						var h = Math.floor((c - 0x10000) / 0x400) + 0xD800;
						var l = (c - 0x10000) % 0x400 + 0xDC00;
						s += String.fromCharCode(h, l);
						continue;
					}
					s += String.fromCharCode(c);
				}
				return s;
			case $kindStruct:
				var timePkg = $packages["time"];
				if (timePkg !== undefined && v.constructor === timePkg.Time.ptr) {
					var milli = $div64(v.UnixNano(), new $Int64(0, 1000000));
					return new Date($flatten64(milli));
				}
				var noJsObject = {};
				var searchJsObject = function(v, t) {
					if (t === $jsObjectPtr) {
						return v;
					}
					switch (t.kind) {
						case $kindPtr:
							if (v === t.nil) {
								return noJsObject;
							}
							return searchJsObject(v.$get(), t.elem);
						case $kindStruct:
							var f = t.fields[0];
							return searchJsObject(v[f.prop], f.typ);
						case $kindInterface:
							return searchJsObject(v.$val, v.constructor);
						default:
							return noJsObject;
					}
				};
				var o = searchJsObject(v, t);
				if (o !== noJsObject) {
					return o;
				}
				o = {};
				for (var i = 0; i < t.fields.length; i++) {
					var f = t.fields[i];
					if (!f.exported) {
						continue;
					}
					o[f.name] = $externalize(v[f.prop], f.typ);
				}
				return o;
		}
		$throwRuntimeError("cannot externalize " + t.string);
	};
	var $externalizeFunction = function(v, t, passThis) {
		if (v === $throwNilPointerError) {
			return null;
		}
		if (v.$externalizeWrapper === undefined) {
			$checkForDeadlock = false;
			v.$externalizeWrapper = function() {
				var args = [];
				for (var i = 0; i < t.params.length; i++) {
					if (t.variadic && i === t.params.length - 1) {
						var vt = t.params[i].elem,
							varargs = [];
						for (var j = i; j < arguments.length; j++) {
							varargs.push($internalize(arguments[j], vt));
						}
						args.push(new(t.params[i])(varargs));
						break;
					}
					args.push($internalize(arguments[i], t.params[i]));
				}
				var result = v.apply(passThis ? this : undefined, args);
				switch (t.results.length) {
					case 0:
						return;
					case 1:
						return $externalize(result, t.results[0]);
					default:
						for (var i = 0; i < t.results.length; i++) {
							result[i] = $externalize(result[i], t.results[i]);
						}
						return result;
				}
			};
		}
		return v.$externalizeWrapper;
	};
	var $internalize = function(v, t, recv) {
		if (t === $jsObjectPtr) {
			return v;
		}
		if (t === $jsObjectPtr.elem) {
			$throwRuntimeError("cannot internalize js.Object, use *js.Object instead");
		}
		if (v && v.__internal_object__ !== undefined) {
			return $assertType(v.__internal_object__, t, false);
		}
		var timePkg = $packages["time"];
		if (timePkg !== undefined && t === timePkg.Time) {
			if (!(v !== null && v !== undefined && v.constructor === Date)) {
				$throwRuntimeError("cannot internalize time.Time from " + typeof v + ", must be Date");
			}
			return timePkg.Unix(new $Int64(0, 0), new $Int64(0, v.getTime() * 1000000));
		}
		switch (t.kind) {
			case $kindBool:
				return !!v;
			case $kindInt:
				return parseInt(v);
			case $kindInt8:
				return parseInt(v) << 24 >> 24;
			case $kindInt16:
				return parseInt(v) << 16 >> 16;
			case $kindInt32:
				return parseInt(v) >> 0;
			case $kindUint:
				return parseInt(v);
			case $kindUint8:
				return parseInt(v) << 24 >>> 24;
			case $kindUint16:
				return parseInt(v) << 16 >>> 16;
			case $kindUint32:
			case $kindUintptr:
				return parseInt(v) >>> 0;
			case $kindInt64:
			case $kindUint64:
				return new t(0, v);
			case $kindFloat32:
			case $kindFloat64:
				return parseFloat(v);
			case $kindArray:
				if (v.length !== t.len) {
					$throwRuntimeError("got array with wrong size from JavaScript native");
				}
				return $mapArray(v, function(e) {
					return $internalize(e, t.elem);
				});
			case $kindFunc:
				return function() {
					var args = [];
					for (var i = 0; i < t.params.length; i++) {
						if (t.variadic && i === t.params.length - 1) {
							var vt = t.params[i].elem,
								varargs = arguments[i];
							for (var j = 0; j < varargs.$length; j++) {
								args.push($externalize(varargs.$array[varargs.$offset + j], vt));
							}
							break;
						}
						args.push($externalize(arguments[i], t.params[i]));
					}
					var result = v.apply(recv, args);
					switch (t.results.length) {
						case 0:
							return;
						case 1:
							return $internalize(result, t.results[0]);
						default:
							for (var i = 0; i < t.results.length; i++) {
								result[i] = $internalize(result[i], t.results[i]);
							}
							return result;
					}
				};
			case $kindInterface:
				if (t.methods.length !== 0) {
					$throwRuntimeError("cannot internalize " + t.string);
				}
				if (v === null) {
					return $ifaceNil;
				}
				if (v === undefined) {
					return new $jsObjectPtr(undefined);
				}
				switch (v.constructor) {
					case Int8Array:
						return new($sliceType($Int8))(v);
					case Int16Array:
						return new($sliceType($Int16))(v);
					case Int32Array:
						return new($sliceType($Int))(v);
					case Uint8Array:
						return new($sliceType($Uint8))(v);
					case Uint16Array:
						return new($sliceType($Uint16))(v);
					case Uint32Array:
						return new($sliceType($Uint))(v);
					case Float32Array:
						return new($sliceType($Float32))(v);
					case Float64Array:
						return new($sliceType($Float64))(v);
					case Array:
						return $internalize(v, $sliceType($emptyInterface));
					case Boolean:
						return new $Bool(!!v);
					case Date:
						if (timePkg === undefined) {
							return new $jsObjectPtr(v);
						}
						return new timePkg.Time($internalize(v, timePkg.Time));
					case Function:
						var funcType = $funcType([$sliceType($emptyInterface)], [$jsObjectPtr], true);
						return new funcType($internalize(v, funcType));
					case Number:
						return new $Float64(parseFloat(v));
					case String:
						return new $String($internalize(v, $String));
					default:
						if ($global.Node && v instanceof $global.Node) {
							return new $jsObjectPtr(v);
						}
						var mapType = $mapType($String, $emptyInterface);
						return new mapType($internalize(v, mapType));
				}
			case $kindMap:
				var m = {};
				var keys = $keys(v);
				for (var i = 0; i < keys.length; i++) {
					var k = $internalize(keys[i], t.key);
					m[t.key.keyFor(k)] = {
						k: k,
						v: $internalize(v[keys[i]], t.elem)
					};
				}
				return m;
			case $kindPtr:
				if (t.elem.kind === $kindStruct) {
					return $internalize(v, t.elem);
				}
			case $kindSlice:
				return new t($mapArray(v, function(e) {
					return $internalize(e, t.elem);
				}));
			case $kindString:
				v = String(v);
				if ($isASCII(v)) {
					return v;
				}
				var s = "";
				var i = 0;
				while (i < v.length) {
					var h = v.charCodeAt(i);
					if (0xD800 <= h && h <= 0xDBFF) {
						var l = v.charCodeAt(i + 1);
						var c = (h - 0xD800) * 0x400 + l - 0xDC00 + 0x10000;
						s += $encodeRune(c);
						i += 2;
						continue;
					}
					s += $encodeRune(h);
					i++;
				}
				return s;
			case $kindStruct:
				var noJsObject = {};
				var searchJsObject = function(t) {
					if (t === $jsObjectPtr) {
						return v;
					}
					if (t === $jsObjectPtr.elem) {
						$throwRuntimeError("cannot internalize js.Object, use *js.Object instead");
					}
					switch (t.kind) {
						case $kindPtr:
							return searchJsObject(t.elem);
						case $kindStruct:
							var f = t.fields[0];
							var o = searchJsObject(f.typ);
							if (o !== noJsObject) {
								var n = new t.ptr();
								n[f.prop] = o;
								return n;
							}
							return noJsObject;
						default:
							return noJsObject;
					}
				};
				var o = searchJsObject(t);
				if (o !== noJsObject) {
					return o;
				}
		}
		$throwRuntimeError("cannot internalize " + t.string);
	};
	var $isASCII = function(s) {
		for (var i = 0; i < s.length; i++) {
			if (s.charCodeAt(i) >= 128) {
				return false;
			}
		}
		return true;
	};
	$packages["github.com/gopherjs/gopherjs/js"] = (function() {
		var $pkg = {},
			$init, Object, Error, sliceType, ptrType, ptrType$1, init;
		Object = $pkg.Object = $newType(0, $kindStruct, "js.Object", true, "github.com/gopherjs/gopherjs/js", true,
			function(object_) {
				this.$val = this;
				if (arguments.length === 0) {
					this.object = null;
					return;
				}
				this.object = object_;
			});
		Error = $pkg.Error = $newType(0, $kindStruct, "js.Error", true, "github.com/gopherjs/gopherjs/js", true, function(
			Object_) {
			this.$val = this;
			if (arguments.length === 0) {
				this.Object = null;
				return;
			}
			this.Object = Object_;
		});
		sliceType = $sliceType($emptyInterface);
		ptrType = $ptrType(Object);
		ptrType$1 = $ptrType(Error);
		Object.ptr.prototype.Get = function(key) {
			var key, o;
			o = this;
			return o.object[$externalize(key, $String)];
		};
		Object.prototype.Get = function(key) {
			return this.$val.Get(key);
		};
		Object.ptr.prototype.Set = function(key, value) {
			var key, o, value;
			o = this;
			o.object[$externalize(key, $String)] = $externalize(value, $emptyInterface);
		};
		Object.prototype.Set = function(key, value) {
			return this.$val.Set(key, value);
		};
		Object.ptr.prototype.Delete = function(key) {
			var key, o;
			o = this;
			delete o.object[$externalize(key, $String)];
		};
		Object.prototype.Delete = function(key) {
			return this.$val.Delete(key);
		};
		Object.ptr.prototype.Length = function() {
			var o;
			o = this;
			return $parseInt(o.object.length);
		};
		Object.prototype.Length = function() {
			return this.$val.Length();
		};
		Object.ptr.prototype.Index = function(i) {
			var i, o;
			o = this;
			return o.object[i];
		};
		Object.prototype.Index = function(i) {
			return this.$val.Index(i);
		};
		Object.ptr.prototype.SetIndex = function(i, value) {
			var i, o, value;
			o = this;
			o.object[i] = $externalize(value, $emptyInterface);
		};
		Object.prototype.SetIndex = function(i, value) {
			return this.$val.SetIndex(i, value);
		};
		Object.ptr.prototype.Call = function(name, args) {
			var args, name, o, obj;
			o = this;
			return (obj = o.object, obj[$externalize(name, $String)].apply(obj, $externalize(args, sliceType)));
		};
		Object.prototype.Call = function(name, args) {
			return this.$val.Call(name, args);
		};
		Object.ptr.prototype.Invoke = function(args) {
			var args, o;
			o = this;
			return o.object.apply(undefined, $externalize(args, sliceType));
		};
		Object.prototype.Invoke = function(args) {
			return this.$val.Invoke(args);
		};
		Object.ptr.prototype.New = function(args) {
			var args, o;
			o = this;
			return new($global.Function.prototype.bind.apply(o.object, [undefined].concat($externalize(args, sliceType))));
		};
		Object.prototype.New = function(args) {
			return this.$val.New(args);
		};
		Object.ptr.prototype.Bool = function() {
			var o;
			o = this;
			return !!(o.object);
		};
		Object.prototype.Bool = function() {
			return this.$val.Bool();
		};
		Object.ptr.prototype.String = function() {
			var o;
			o = this;
			return $internalize(o.object, $String);
		};
		Object.prototype.String = function() {
			return this.$val.String();
		};
		Object.ptr.prototype.Int = function() {
			var o;
			o = this;
			return $parseInt(o.object) >> 0;
		};
		Object.prototype.Int = function() {
			return this.$val.Int();
		};
		Object.ptr.prototype.Int64 = function() {
			var o;
			o = this;
			return $internalize(o.object, $Int64);
		};
		Object.prototype.Int64 = function() {
			return this.$val.Int64();
		};
		Object.ptr.prototype.Uint64 = function() {
			var o;
			o = this;
			return $internalize(o.object, $Uint64);
		};
		Object.prototype.Uint64 = function() {
			return this.$val.Uint64();
		};
		Object.ptr.prototype.Float = function() {
			var o;
			o = this;
			return $parseFloat(o.object);
		};
		Object.prototype.Float = function() {
			return this.$val.Float();
		};
		Object.ptr.prototype.Interface = function() {
			var o;
			o = this;
			return $internalize(o.object, $emptyInterface);
		};
		Object.prototype.Interface = function() {
			return this.$val.Interface();
		};
		Object.ptr.prototype.Unsafe = function() {
			var o;
			o = this;
			return o.object;
		};
		Object.prototype.Unsafe = function() {
			return this.$val.Unsafe();
		};
		Error.ptr.prototype.Error = function() {
			var err;
			err = this;
			return "JavaScript error: " + $internalize(err.Object.message, $String);
		};
		Error.prototype.Error = function() {
			return this.$val.Error();
		};
		Error.ptr.prototype.Stack = function() {
			var err;
			err = this;
			return $internalize(err.Object.stack, $String);
		};
		Error.prototype.Stack = function() {
			return this.$val.Stack();
		};
		init = function() {
			var e;
			e = new Error.ptr(null);
			$unused(e);
		};
		ptrType.methods = [{
			prop: "Get",
			name: "Get",
			pkg: "",
			typ: $funcType([$String], [ptrType], false)
		}, {
			prop: "Set",
			name: "Set",
			pkg: "",
			typ: $funcType([$String, $emptyInterface], [], false)
		}, {
			prop: "Delete",
			name: "Delete",
			pkg: "",
			typ: $funcType([$String], [], false)
		}, {
			prop: "Length",
			name: "Length",
			pkg: "",
			typ: $funcType([], [$Int], false)
		}, {
			prop: "Index",
			name: "Index",
			pkg: "",
			typ: $funcType([$Int], [ptrType], false)
		}, {
			prop: "SetIndex",
			name: "SetIndex",
			pkg: "",
			typ: $funcType([$Int, $emptyInterface], [], false)
		}, {
			prop: "Call",
			name: "Call",
			pkg: "",
			typ: $funcType([$String, sliceType], [ptrType], true)
		}, {
			prop: "Invoke",
			name: "Invoke",
			pkg: "",
			typ: $funcType([sliceType], [ptrType], true)
		}, {
			prop: "New",
			name: "New",
			pkg: "",
			typ: $funcType([sliceType], [ptrType], true)
		}, {
			prop: "Bool",
			name: "Bool",
			pkg: "",
			typ: $funcType([], [$Bool], false)
		}, {
			prop: "String",
			name: "String",
			pkg: "",
			typ: $funcType([], [$String], false)
		}, {
			prop: "Int",
			name: "Int",
			pkg: "",
			typ: $funcType([], [$Int], false)
		}, {
			prop: "Int64",
			name: "Int64",
			pkg: "",
			typ: $funcType([], [$Int64], false)
		}, {
			prop: "Uint64",
			name: "Uint64",
			pkg: "",
			typ: $funcType([], [$Uint64], false)
		}, {
			prop: "Float",
			name: "Float",
			pkg: "",
			typ: $funcType([], [$Float64], false)
		}, {
			prop: "Interface",
			name: "Interface",
			pkg: "",
			typ: $funcType([], [$emptyInterface], false)
		}, {
			prop: "Unsafe",
			name: "Unsafe",
			pkg: "",
			typ: $funcType([], [$Uintptr], false)
		}];
		ptrType$1.methods = [{
			prop: "Error",
			name: "Error",
			pkg: "",
			typ: $funcType([], [$String], false)
		}, {
			prop: "Stack",
			name: "Stack",
			pkg: "",
			typ: $funcType([], [$String], false)
		}];
		Object.init("github.com/gopherjs/gopherjs/js", [{
			prop: "object",
			name: "object",
			anonymous: false,
			exported: false,
			typ: ptrType,
			tag: ""
		}]);
		Error.init("", [{
			prop: "Object",
			name: "Object",
			anonymous: true,
			exported: true,
			typ: ptrType,
			tag: ""
		}]);
		$init = function() {
			$pkg.$init = function() {};
			var $f, $c = false,
				$s = 0,
				$r;
			if (this !== undefined && this.$blk !== undefined) {
				$f = this;
				$c = true;
				$s = $f.$s;
				$r = $f.$r;
			}
			s: while (true) {
				switch ($s) {
					case 0:
						init();
				}
				return;
			}
			if ($f === undefined) {
				$f = {
					$blk: $init
				};
			}
			$f.$s = $s;
			$f.$r = $r;
			return $f;
		};
		$pkg.$init = $init;
		return $pkg;
	})();
	$packages["runtime/internal/sys"] = (function() {
		var $pkg = {},
			$init;
		$init = function() {
			$pkg.$init = function() {};
			var $f, $c = false,
				$s = 0,
				$r;
			if (this !== undefined && this.$blk !== undefined) {
				$f = this;
				$c = true;
				$s = $f.$s;
				$r = $f.$r;
			}
			s: while (true) {
				switch ($s) {
					case 0:
				}
				return;
			}
			if ($f === undefined) {
				$f = {
					$blk: $init
				};
			}
			$f.$s = $s;
			$f.$r = $r;
			return $f;
		};
		$pkg.$init = $init;
		return $pkg;
	})();
	$packages["runtime"] = (function() {
		var $pkg = {},
			$init, js, sys, TypeAssertionError, errorString, ptrType$4, init, throw$1;
		js = $packages["github.com/gopherjs/gopherjs/js"];
		sys = $packages["runtime/internal/sys"];
		TypeAssertionError = $pkg.TypeAssertionError = $newType(0, $kindStruct, "runtime.TypeAssertionError", true,
			"runtime", true,
			function(interfaceString_, concreteString_, assertedString_, missingMethod_) {
				this.$val = this;
				if (arguments.length === 0) {
					this.interfaceString = "";
					this.concreteString = "";
					this.assertedString = "";
					this.missingMethod = "";
					return;
				}
				this.interfaceString = interfaceString_;
				this.concreteString = concreteString_;
				this.assertedString = assertedString_;
				this.missingMethod = missingMethod_;
			});
		errorString = $pkg.errorString = $newType(8, $kindString, "runtime.errorString", true, "runtime", false, null);
		ptrType$4 = $ptrType(TypeAssertionError);
		init = function() {
			var e, jsPkg;
			jsPkg = $packages[$externalize("github.com/gopherjs/gopherjs/js", $String)];
			$jsObjectPtr = jsPkg.Object.ptr;
			$jsErrorPtr = jsPkg.Error.ptr;
			$throwRuntimeError = throw$1;
			e = $ifaceNil;
			e = new TypeAssertionError.ptr("", "", "", "");
			$unused(e);
		};
		throw$1 = function(s) {
			var s;
			$panic(new errorString((s)));
		};
		TypeAssertionError.ptr.prototype.RuntimeError = function() {};
		TypeAssertionError.prototype.RuntimeError = function() {
			return this.$val.RuntimeError();
		};
		TypeAssertionError.ptr.prototype.Error = function() {
			var e, inter;
			e = this;
			inter = e.interfaceString;
			if (inter === "") {
				inter = "interface";
			}
			if (e.concreteString === "") {
				return "interface conversion: " + inter + " is nil, not " + e.assertedString;
			}
			if (e.missingMethod === "") {
				return "interface conversion: " + inter + " is " + e.concreteString + ", not " + e.assertedString;
			}
			return "interface conversion: " + e.concreteString + " is not " + e.assertedString + ": missing method " + e.missingMethod;
		};
		TypeAssertionError.prototype.Error = function() {
			return this.$val.Error();
		};
		errorString.prototype.RuntimeError = function() {
			var e;
			e = this.$val;
		};
		$ptrType(errorString).prototype.RuntimeError = function() {
			return new errorString(this.$get()).RuntimeError();
		};
		errorString.prototype.Error = function() {
			var e;
			e = this.$val;
			return "runtime error: " + (e);
		};
		$ptrType(errorString).prototype.Error = function() {
			return new errorString(this.$get()).Error();
		};
		ptrType$4.methods = [{
			prop: "RuntimeError",
			name: "RuntimeError",
			pkg: "",
			typ: $funcType([], [], false)
		}, {
			prop: "Error",
			name: "Error",
			pkg: "",
			typ: $funcType([], [$String], false)
		}];
		errorString.methods = [{
			prop: "RuntimeError",
			name: "RuntimeError",
			pkg: "",
			typ: $funcType([], [], false)
		}, {
			prop: "Error",
			name: "Error",
			pkg: "",
			typ: $funcType([], [$String], false)
		}];
		TypeAssertionError.init("runtime", [{
			prop: "interfaceString",
			name: "interfaceString",
			anonymous: false,
			exported: false,
			typ: $String,
			tag: ""
		}, {
			prop: "concreteString",
			name: "concreteString",
			anonymous: false,
			exported: false,
			typ: $String,
			tag: ""
		}, {
			prop: "assertedString",
			name: "assertedString",
			anonymous: false,
			exported: false,
			typ: $String,
			tag: ""
		}, {
			prop: "missingMethod",
			name: "missingMethod",
			anonymous: false,
			exported: false,
			typ: $String,
			tag: ""
		}]);
		$init = function() {
			$pkg.$init = function() {};
			var $f, $c = false,
				$s = 0,
				$r;
			if (this !== undefined && this.$blk !== undefined) {
				$f = this;
				$c = true;
				$s = $f.$s;
				$r = $f.$r;
			}
			s: while (true) {
				switch ($s) {
					case 0:
						$r = js.$init();
						$s = 1;
					case 1:
						if ($c) {
							$c = false;
							$r = $r.$blk();
						}
						if ($r && $r.$blk !== undefined) {
							break s;
						}
						$r = sys.$init();
						$s = 2;
					case 2:
						if ($c) {
							$c = false;
							$r = $r.$blk();
						}
						if ($r && $r.$blk !== undefined) {
							break s;
						}
						init();
				}
				return;
			}
			if ($f === undefined) {
				$f = {
					$blk: $init
				};
			}
			$f.$s = $s;
			$f.$r = $r;
			return $f;
		};
		$pkg.$init = $init;
		return $pkg;
	})();
	$packages["main"] = (function() {
		var $pkg = {},
			$init, js, Duration, DigitalRain, waterDrop, GlyphCanvas, ptrType, sliceType, sliceType$1, funcType, ptrType$1,
			sliceType$2, ptrType$2, ptrType$3, funcType$1, sliceType$3, mapType, mapType$1, overlap, githubLinkColor,
			githubLinkOverColor, githubLink, level1Cols, level2Cols, lowGlyphCanvases, highGlyphCanvases, backgrounds, index,
			main, itoa, ftoa, randi, NewDigitalRain, shortLink, NewGlyphCanvas;
		js = $packages["github.com/gopherjs/gopherjs/js"];
		Duration = $pkg.Duration = $newType(8, $kindFloat64, "main.Duration", true, "main", true, null);
		DigitalRain = $pkg.DigitalRain = $newType(0, $kindStruct, "main.DigitalRain", true, "main", true, function(parent_,
			canvas_, ctx_, width_, height_, ratio_, timestamp_, lowGlyphCanvas_, highGlyphCanvas_, drops_, linkover_,
			screenCols_, minSpeed_, maxSpeed_, brightness_, Clicked_) {
			this.$val = this;
			if (arguments.length === 0) {
				this.parent = null;
				this.canvas = null;
				this.ctx = null;
				this.width = 0;
				this.height = 0;
				this.ratio = 0;
				this.timestamp = 0;
				this.lowGlyphCanvas = ptrType.nil;
				this.highGlyphCanvas = ptrType.nil;
				this.drops = sliceType$2.nil;
				this.linkover = false;
				this.screenCols = 0;
				this.minSpeed = 0;
				this.maxSpeed = 0;
				this.brightness = 0;
				this.Clicked = $throwNilPointerError;
				return;
			}
			this.parent = parent_;
			this.canvas = canvas_;
			this.ctx = ctx_;
			this.width = width_;
			this.height = height_;
			this.ratio = ratio_;
			this.timestamp = timestamp_;
			this.lowGlyphCanvas = lowGlyphCanvas_;
			this.highGlyphCanvas = highGlyphCanvas_;
			this.drops = drops_;
			this.linkover = linkover_;
			this.screenCols = screenCols_;
			this.minSpeed = minSpeed_;
			this.maxSpeed = maxSpeed_;
			this.brightness = brightness_;
			this.Clicked = Clicked_;
		});
		waterDrop = $pkg.waterDrop = $newType(0, $kindStruct, "main.waterDrop", true, "main", false, function(col_, row_,
			start_, speed_, glyphs_, spedup_, created_) {
			this.$val = this;
			if (arguments.length === 0) {
				this.col = 0;
				this.row = 0;
				this.start = 0;
				this.speed = 0;
				this.glyphs = sliceType$3.nil;
				this.spedup = false;
				this.created = 0;
				return;
			}
			this.col = col_;
			this.row = row_;
			this.start = start_;
			this.speed = speed_;
			this.glyphs = glyphs_;
			this.spedup = spedup_;
			this.created = created_;
		});
		GlyphCanvas = $pkg.GlyphCanvas = $newType(0, $kindStruct, "main.GlyphCanvas", true, "main", true, function(jso_,
			glyphs_) {
			this.$val = this;
			if (arguments.length === 0) {
				this.jso = null;
				this.glyphs = false;
				return;
			}
			this.jso = jso_;
			this.glyphs = glyphs_;
		});
		ptrType = $ptrType(GlyphCanvas);
		sliceType = $sliceType(ptrType);
		sliceType$1 = $sliceType($String);
		funcType = $funcType([], [], false);
		ptrType$1 = $ptrType(waterDrop);
		sliceType$2 = $sliceType(ptrType$1);
		ptrType$2 = $ptrType(DigitalRain);
		ptrType$3 = $ptrType(js.Object);
		funcType$1 = $funcType([ptrType$3], [], false);
		sliceType$3 = $sliceType($Int);
		mapType = $mapType($Int, ptrType$3);
		mapType$1 = $mapType($Int, mapType);
		main = function() {
			var sheet;
			sheet = $global.document.createElement($externalize("style", $String));
			sheet.innerHTML = $externalize(
				"html, body { \n\t\t\tpadding:0; margin:0; border:0; width:100%; height:100%; overflow:hidden;\n\t\t}\n\t\thtml{\n\t\t\tbackground: black;\n\t\t}",
				$String);
			$global.document.head.appendChild(sheet);
			$global.document.title = $externalize("whoa", $String);
			$global.addEventListener($externalize("load", $String), $externalize((function $b() {
				var _r, _r$1, _tuple, _tuple$1, cover, err, rain1, rain2, $s, $r;
				$s = 0;
				var $f, $c = false;
				if (this !== undefined && this.$blk !== undefined) {
					$f = this;
					$c = true;
					_r = $f._r;
					_r$1 = $f._r$1;
					_tuple = $f._tuple;
					_tuple$1 = $f._tuple$1;
					cover = $f.cover;
					err = $f.err;
					rain1 = $f.rain1;
					rain2 = $f.rain2;
					$s = $f.$s;
					$r = $f.$r;
				}
				s: while (true) {
					switch ($s) {
						case 0:
							rain1 = [rain1];
							rain2 = [rain2];
							lowGlyphCanvases = new sliceType([NewGlyphCanvas("#01334a"), NewGlyphCanvas("#3b806d")]);
							highGlyphCanvases = new sliceType([NewGlyphCanvas("#01334a"), NewGlyphCanvas("#5b9b9b")]);
							backgrounds = new sliceType$1(["#dcedfe", "#000000"]);
							_tuple = NewDigitalRain($global.document.body, level2Cols, 2, 8, 0.25);
							rain1[0] = _tuple[0];
							err = _tuple[1];
							if (!($interfaceIsEqual(err, $ifaceNil))) {
								$s = 1;
								continue;
							}
							$s = 2;
							continue;
						case 1:
							_r = err.Error();
							$s = 3;
						case 3:
							if ($c) {
								$c = false;
								_r = _r.$blk();
							}
							if (_r && _r.$blk !== undefined) {
								break s;
							}
							console.log(_r);
							$s = -1;
							return;
						case 2:
							cover = $global.document.createElement($externalize("div", $String));
							cover.style.height = $externalize("100%", $String);
							cover.style.width = $externalize("100%", $String);
							cover.style[$externalize("background-image", $String)] = $externalize(
								"radial-gradient(ellipse farthest-corner at 45px 45px , #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%)",
								$String);
							cover.style.opacity = $externalize("0.18", $String);
							cover.style.position = $externalize("absolute", $String);
							$global.document.body.appendChild(cover);
							$global.addEventListener($externalize("resize", $String), $externalize((function(rain1, rain2) {
								return function() {
									rain1[0].layout();
								};
							})(rain1, rain2), funcType));
							_tuple$1 = NewDigitalRain($global.document.body, level1Cols, 2, 12, 1);
							rain2[0] = _tuple$1[0];
							err = _tuple$1[1];
							if (!($interfaceIsEqual(err, $ifaceNil))) {
								$s = 4;
								continue;
							}
							$s = 5;
							continue;
						case 4:
							_r$1 = err.Error();
							$s = 6;
						case 6:
							if ($c) {
								$c = false;
								_r$1 = _r$1.$blk();
							}
							if (_r$1 && _r$1.$blk !== undefined) {
								break s;
							}
							console.log(_r$1);
							$s = -1;
							return;
						case 5:
							$global.addEventListener($externalize("resize", $String), $externalize((function(rain1, rain2) {
								return function() {
									rain2[0].layout();
								};
							})(rain1, rain2), funcType));
							rain2[0].Clicked = (function(rain1, rain2) {
								return function() {
									var _r$2, _r$3, _r$4, _r$5, _r$6, x, x$1, x$2, x$3, x$4;
									return;
									index = index + (1) >> 0;
									rain1[0].lowGlyphCanvas = (x = (_r$2 = index % 2, _r$2 === _r$2 ? _r$2 : $throwRuntimeError(
										"integer divide by zero")), ((x < 0 || x >= lowGlyphCanvases.$length) ? ($throwRuntimeError(
										"index out of range"), undefined) : lowGlyphCanvases.$array[lowGlyphCanvases.$offset + x]));
									rain1[0].highGlyphCanvas = (x$1 = (_r$3 = index % 2, _r$3 === _r$3 ? _r$3 : $throwRuntimeError(
										"integer divide by zero")), ((x$1 < 0 || x$1 >= highGlyphCanvases.$length) ? (
										$throwRuntimeError("index out of range"), undefined) : highGlyphCanvases.$array[
										highGlyphCanvases.$offset + x$1]));
									rain2[0].lowGlyphCanvas = (x$2 = (_r$4 = index % 2, _r$4 === _r$4 ? _r$4 : $throwRuntimeError(
										"integer divide by zero")), ((x$2 < 0 || x$2 >= lowGlyphCanvases.$length) ? ($throwRuntimeError(
										"index out of range"), undefined) : lowGlyphCanvases.$array[lowGlyphCanvases.$offset + x$2]));
									rain2[0].highGlyphCanvas = (x$3 = (_r$5 = index % 2, _r$5 === _r$5 ? _r$5 : $throwRuntimeError(
										"integer divide by zero")), ((x$3 < 0 || x$3 >= highGlyphCanvases.$length) ? (
										$throwRuntimeError("index out of range"), undefined) : highGlyphCanvases.$array[
										highGlyphCanvases.$offset + x$3]));
									$global.document.body.style.background = $externalize((x$4 = (_r$6 = index % 2, _r$6 === _r$6 ?
										_r$6 : $throwRuntimeError("integer divide by zero")), ((x$4 < 0 || x$4 >= backgrounds.$length) ?
										($throwRuntimeError("index out of range"), undefined) : backgrounds.$array[backgrounds.$offset +
											x$4])), $String);
								};
							})(rain1, rain2);
							$s = -1;
							return;
					}
					return;
				}
				if ($f === undefined) {
					$f = {
						$blk: $b
					};
				}
				$f._r = _r;
				$f._r$1 = _r$1;
				$f._tuple = _tuple;
				$f._tuple$1 = _tuple$1;
				$f.cover = cover;
				$f.err = err;
				$f.rain1 = rain1;
				$f.rain2 = rain2;
				$f.$s = $s;
				$f.$r = $r;
				return $f;
			}), funcType));
		};
		itoa = function(i) {
			var i;
			return $internalize(new($global.String)(i), $String);
		};
		ftoa = function(f) {
			var f;
			return $internalize(new($global.String)(f), $String);
		};
		randi = function() {
			return (($parseFloat($global.Math.random()) * 2.147483647e+09 >> 0));
		};
		NewDigitalRain = function(parent, screenCols, minSpeed, maxSpeed, brightness) {
			var brightness, err, maxSpeed, minSpeed, parent, rain, screenCols;
			rain = new DigitalRain.ptr(parent, null, null, 0, 0, 0, 0, ptrType.nil, ptrType.nil, sliceType$2.nil, false, 0,
				0, 0, 0, $throwNilPointerError);
			rain.screenCols = screenCols;
			rain.minSpeed = minSpeed;
			rain.maxSpeed = maxSpeed;
			rain.brightness = brightness;
			err = rain.start();
			if (!($interfaceIsEqual(err, $ifaceNil))) {
				return [ptrType$2.nil, err];
			}
			return [rain, $ifaceNil];
		};
		$pkg.NewDigitalRain = NewDigitalRain;
		DigitalRain.ptr.prototype.start = function() {
			var _i, _ref, f, r, raf, s, $deferred;
			var $err = null;
			try {
				$deferred = [];
				$deferred.index = $curGoroutine.deferStack.length;
				$curGoroutine.deferStack.push($deferred);
				r = this;
				raf = "";
				_ref = new sliceType$1(["requestAnimationFrame", "webkitRequestAnimationFrame", "mozRequestAnimationFrame"]);
				_i = 0;
				while (true) {
					if (!(_i < _ref.$length)) {
						break;
					}
					s = ((_i < 0 || _i >= _ref.$length) ? ($throwRuntimeError("index out of range"), undefined) : _ref.$array[_ref
						.$offset + _i]);
					if (!($global[$externalize(s, $String)] === undefined)) {
						raf = s;
						break;
					}
					_i++;
				}
				if (raf === "") {
					$panic(new $String("requestAnimationFrame is not available"));
				}
				$deferred.push([$methodVal(r, "layout"), []]);
				f = $throwNilPointerError;
				f = (function(timestampJS) {
					var timestampJS;
					$global[$externalize(raf, $String)]($externalize(f, funcType$1));
					r.loop(($parseFloat(timestampJS) / 1000));
				});
				$global[$externalize(raf, $String)]($externalize(f, funcType$1));
				return $ifaceNil;
			} catch (err) {
				$err = err;
				return $ifaceNil;
			} finally {
				$callDeferred($deferred, $err);
			}
		};
		DigitalRain.prototype.start = function() {
			return this.$val.start();
		};
		DigitalRain.ptr.prototype.layout = function() {
			var _r, _r$1, _tmp, _tmp$1, _tmp$2, height, r, ratio, width, x, x$1;
			r = this;
			ratio = $parseFloat($global.devicePixelRatio);
			width = $parseFloat(r.parent.offsetWidth) * ratio;
			height = $parseFloat(r.parent.offsetHeight) * ratio;
			if (!(r.canvas === null) && (r.width === width) && (r.height === height) && (r.ratio === ratio)) {
				return;
			}
			_tmp = width;
			_tmp$1 = height;
			_tmp$2 = ratio;
			r.width = _tmp;
			r.height = _tmp$1;
			r.ratio = _tmp$2;
			if (!(r.canvas === null)) {
				r.parent.removeChild(r.canvas);
			}
			r.canvas = $global.document.createElement($externalize("canvas", $String));
			r.ctx = r.canvas.getContext($externalize("2d", $String));
			r.canvas.width = r.width;
			r.canvas.height = r.height;
			r.canvas.style.width = $externalize(ftoa(r.width / r.ratio) + "px", $String);
			r.canvas.style.height = $externalize(ftoa(r.height / r.ratio) + "px", $String);
			r.canvas.style.position = $externalize("absolute", $String);
			r.parent.appendChild(r.canvas);
			if (r.highGlyphCanvas === ptrType.nil) {
				r.highGlyphCanvas = (x = (_r = index % 2, _r === _r ? _r : $throwRuntimeError("integer divide by zero")), ((x <
						0 || x >= highGlyphCanvases.$length) ? ($throwRuntimeError("index out of range"), undefined) :
					highGlyphCanvases.$array[highGlyphCanvases.$offset + x]));
			}
			if (r.lowGlyphCanvas === ptrType.nil) {
				r.lowGlyphCanvas = (x$1 = (_r$1 = index % 2, _r$1 === _r$1 ? _r$1 : $throwRuntimeError("integer divide by zero")),
					((x$1 < 0 || x$1 >= lowGlyphCanvases.$length) ? ($throwRuntimeError("index out of range"), undefined) :
						lowGlyphCanvases.$array[lowGlyphCanvases.$offset + x$1]));
			}
			r.canvas.addEventListener($externalize("click", $String), $externalize((function $b(ev) {
				var ev, $s, $r;
				$s = 0;
				var $f, $c = false;
				if (this !== undefined && this.$blk !== undefined) {
					$f = this;
					$c = true;
					ev = $f.ev;
					$s = $f.$s;
					$r = $f.$r;
				}
				s: while (true) {
					switch ($s) {
						case 0:
							if (r.overLink($parseInt(ev.x) >> 0, $parseInt(ev.y) >> 0)) {
								$s = 1;
								continue;
							}
							$s = 2;
							continue;
						case 1:
							$global.location = $externalize(githubLink, $String);
							$s = 3;
							continue;
						case 2:
							if (!(r.Clicked === $throwNilPointerError)) {
								$s = 4;
								continue;
							}
							$s = 5;
							continue;
						case 4:
							$r = r.Clicked();
							$s = 6;
						case 6:
							if ($c) {
								$c = false;
								$r = $r.$blk();
							}
							if ($r && $r.$blk !== undefined) {
								break s;
							}
						case 5:
						case 3:
							$s = -1;
							return;
					}
					return;
				}
				if ($f === undefined) {
					$f = {
						$blk: $b
					};
				}
				$f.ev = ev;
				$f.$s = $s;
				$f.$r = $r;
				return $f;
			}), funcType$1));
			r.canvas.addEventListener($externalize("mousemove", $String), $externalize((function(ev) {
				var ev;
				if (r.overLink($parseInt(ev.x) >> 0, $parseInt(ev.y) >> 0)) {
					r.canvas.style.cursor = $externalize("pointer", $String);
					r.linkover = true;
				} else {
					r.canvas.style.cursor = $externalize("default", $String);
					r.linkover = false;
				}
			}), funcType$1));
			r.loop(r.timestamp);
		};
		DigitalRain.prototype.layout = function() {
			return this.$val.layout();
		};
		DigitalRain.ptr.prototype.overLink = function(x, y) {
			var r, x, y;
			r = this;
			return x > (((r.width / r.ratio >> 0)) - 320 >> 0) && y > (((r.height / r.ratio >> 0)) - 50 >> 0);
		};
		DigitalRain.prototype.overLink = function(x, y) {
			return this.$val.overLink(x, y);
		};
		DigitalRain.ptr.prototype.dropWaterAtCol = function(col, speed, length, start, created) {
			var _r, col, created, i, length, r, speed, start, wd, x;
			r = this;
			wd = new waterDrop.ptr(0, 0, 0, 0, sliceType$3.nil, false, 0);
			wd.col = col;
			wd.speed = speed;
			wd.glyphs = $makeSlice(sliceType$3, length);
			i = 0;
			while (true) {
				if (!(i < length)) {
					break;
				}
				(x = wd.glyphs, ((i < 0 || i >= x.$length) ? ($throwRuntimeError("index out of range"), undefined) : x.$array[x
					.$offset + i] = (_r = randi() % 72, _r === _r ? _r : $throwRuntimeError("integer divide by zero"))));
				i = i + (1) >> 0;
			}
			r.drops = $append(r.drops, wd);
			wd.row = start;
			wd.start = wd.row;
			wd.created = created;
		};
		DigitalRain.prototype.dropWaterAtCol = function(col, speed, length, start, created) {
			return this.$val.dropWaterAtCol(col, speed, length, start, created);
		};
		DigitalRain.ptr.prototype.dropRandomWaterDrop = function(timestamp) {
			var _i, _q, _r, _r$1, _r$2, _r$3, _ref, col, colcnt, drop, length, r, speed, start, timestamp;
			r = this;
			col = (_r = randi() % r.screenCols, _r === _r ? _r : $throwRuntimeError("integer divide by zero"));
			colcnt = 0;
			_ref = r.drops;
			_i = 0;
			while (true) {
				if (!(_i < _ref.$length)) {
					break;
				}
				drop = ((_i < 0 || _i >= _ref.$length) ? ($throwRuntimeError("index out of range"), undefined) : _ref.$array[
					_ref.$offset + _i]);
				if ((drop.col === col) && (((drop.row >> 0)) - drop.glyphs.$length >> 0) < 0) {
					colcnt = colcnt + (1) >> 0;
					if (colcnt > overlap) {
						return;
					}
				}
				_i++;
			}
			speed = (((_r$1 = randi() % ((r.maxSpeed - r.minSpeed >> 0)), _r$1 === _r$1 ? _r$1 : $throwRuntimeError(
				"integer divide by zero")) + r.minSpeed >> 0));
			length = (_r$2 = randi() % 30, _r$2 === _r$2 ? _r$2 : $throwRuntimeError("integer divide by zero")) + 10 >> 0;
			start = ((((_r$3 = randi() % r.maxRows(), _r$3 === _r$3 ? _r$3 : $throwRuntimeError("integer divide by zero"))) -
				(_q = r.maxRows() / 2, (_q === _q && _q !== 1 / 0 && _q !== -1 / 0) ? _q >> 0 : $throwRuntimeError(
					"integer divide by zero")) >> 0));
			r.dropWaterAtCol(col, speed, length, start, timestamp);
		};
		DigitalRain.prototype.dropRandomWaterDrop = function(timestamp) {
			return this.$val.dropRandomWaterDrop(timestamp);
		};
		DigitalRain.ptr.prototype.maxRows = function() {
			var cellSize, r;
			r = this;
			cellSize = r.width / (r.screenCols);
			return (((r.height / cellSize) + 2 >> 0));
		};
		DigitalRain.prototype.maxRows = function() {
			return this.$val.maxRows();
		};
		DigitalRain.ptr.prototype.drawGlyphAt = function(nidx, col, row, brightness, head) {
			var brightness, col, head, nidx, r, row;
			r = this;
			if (col < 0 || col > r.screenCols || row < -1 || row > (r.maxRows())) {
				return;
			}
			r.drawGlyphElAt(r.lowGlyphCanvas, nidx, col, row, brightness);
			if (head) {
				r.drawGlyphElAt(r.highGlyphCanvas, nidx, col, row, brightness);
			}
		};
		DigitalRain.prototype.drawGlyphAt = function(nidx, col, row, brightness, head) {
			return this.$val.drawGlyphAt(nidx, col, row, brightness, head);
		};
		DigitalRain.ptr.prototype.drawGlyphElAt = function(glyphCanvas, nidx, col, row, brightness) {
			var _q, _r, brightness, cellSize, col, cx, cy, glyph, glyphCanvas, gx, gy, nidx, r, row;
			r = this;
			if (brightness <= 0.05) {
				return;
			}
			if (brightness > 1) {
				brightness = 1;
			}
			cellSize = r.width / (r.screenCols);
			gy = $imul(((_q = nidx / 18, (_q === _q && _q !== 1 / 0 && _q !== -1 / 0) ? _q >> 0 : $throwRuntimeError(
				"integer divide by zero"))), 100);
			gx = $imul(((_r = nidx % 18, _r === _r ? _r : $throwRuntimeError("integer divide by zero"))), 100);
			cx = cellSize * (col) + cellSize / 2 - (cellSize * 1.5) / 2;
			cy = cellSize * (row);
			glyph = glyphCanvas.Glyph(gx, gy);
			if (!(glyph === null)) {
				r.ctx.save();
				r.ctx.globalAlpha = brightness;
				r.ctx.drawImage(glyph, cx, cy, cellSize * 1.5, cellSize * 1.5);
				r.ctx.restore();
			}
		};
		DigitalRain.prototype.drawGlyphElAt = function(glyphCanvas, nidx, col, row, brightness) {
			return this.$val.drawGlyphElAt(glyphCanvas, nidx, col, row, brightness);
		};
		shortLink = function(link) {
			var i, link;
			i = 0;
			while (true) {
				if (!(i < link.length)) {
					break;
				}
				if ((link.charCodeAt(i) === 58) && (i + 2 >> 0) < link.length && (link.charCodeAt((i + 1 >> 0)) === 47) && (
						link.charCodeAt((i + 2 >> 0)) === 47)) {
					return $substring(link, (i + 3 >> 0));
				}
				i = i + (1) >> 0;
			}
			return link;
		};
		DigitalRain.ptr.prototype.drawTitle = function(text, color, fontSize, y) {
			var color, fontSize, ny, pad, r, text, x, y;
			r = this;
			ny = y + (fontSize * 1.5);
			pad = 15 * r.ratio;
			x = r.width - pad;
			y = r.height - pad - y;
			r.ctx.save();
			r.ctx.font = $externalize(itoa(((fontSize >> 0))) +
				"px Menlo, Consolas, Monospace, Helvetica, Arial, Sans-Serif", $String);
			r.ctx.textAlign = $externalize("right", $String);
			r.ctx.lineWidth = 0;
			r.ctx.shadowColor = $externalize(color, $String);
			r.ctx.shadowBlur = (fontSize);
			r.ctx.fillStyle = $externalize(color, $String);
			r.ctx.fillText($externalize(text, $String), x, y);
			r.ctx.restore();
			return ny;
		};
		DigitalRain.prototype.drawTitle = function(text, color, fontSize, y) {
			return this.$val.drawTitle(text, color, fontSize, y);
		};
		DigitalRain.ptr.prototype.drawTitles = function() {
			var r, y;
			r = this;
			y = 0;
			if (r.linkover) {
				y = r.drawTitle(shortLink(githubLink), githubLinkOverColor, 15 * r.ratio, y);
			} else {
				y = r.drawTitle(shortLink(githubLink), githubLinkColor, 15 * r.ratio, y);
			}
		};
		DigitalRain.prototype.drawTitles = function() {
			return this.$val.drawTitles();
		};
		DigitalRain.ptr.prototype.loop = function(timestamp) {
			var _i, _r, _r$1, _r$2, _r$3, _ref, age, brightness, drop, drops, elapsed, gbrightness, gcount, gl, glyph, i, r,
				ri, ri$1, row, timestamp, x, x$1, $deferred;
			var $err = null;
			try {
				$deferred = [];
				$deferred.index = $curGoroutine.deferStack.length;
				$curGoroutine.deferStack.push($deferred);
				r = this;
				if ((timestamp === 0) || (r.timestamp === 0)) {
					r.timestamp = timestamp;
					return;
				}
				elapsed = timestamp - r.timestamp;
				r.timestamp = timestamp;
				r.dropRandomWaterDrop(timestamp);
				r.ctx.clearRect(0, 0, r.width, r.height);
				$deferred.push([$methodVal(r, "drawTitles"), []]);
				drops = sliceType$2.nil;
				_ref = r.drops;
				_i = 0;
				while (true) {
					if (!(_i < _ref.$length)) {
						break;
					}
					drop = ((_i < 0 || _i >= _ref.$length) ? ($throwRuntimeError("index out of range"), undefined) : _ref.$array[
						_ref.$offset + _i]);
					ri = randi();
					if (!drop.spedup) {
						if ((_r = ri % 250, _r === _r ? _r : $throwRuntimeError("integer divide by zero")) === 0) {
							drop.speed = drop.speed * (((_r$1 = ri % 3, _r$1 === _r$1 ? _r$1 : $throwRuntimeError(
								"integer divide by zero"))) + 0.8);
							drop.spedup = true;
						}
					}
					gbrightness = r.brightness;
					age = timestamp - drop.created;
					if (age < 1) {
						gbrightness = (age / 1);
					}
					drop.row = drop.row + ((elapsed) / 1 * drop.speed);
					gl = drop.glyphs.$length;
					if ((((drop.row >> 0)) - gl >> 0) > r.maxRows()) {
						_i++;
						continue;
					}
					drops = $append(drops, drop);
					gcount = ((drop.row - drop.start >> 0));
					if (gcount > drop.glyphs.$length) {
						gcount = drop.glyphs.$length;
					}
					i = 0;
					while (true) {
						if (!(i < gcount)) {
							break;
						}
						ri$1 = randi();
						glyph = (x = drop.glyphs, ((i < 0 || i >= x.$length) ? ($throwRuntimeError("index out of range"), undefined) :
							x.$array[x.$offset + i]));
						brightness = 1 - ((i) / (gcount));
						if ((_r$2 = ri$1 % 50, _r$2 === _r$2 ? _r$2 : $throwRuntimeError("integer divide by zero")) === 0) {
							glyph = (_r$3 = ri$1 % 72, _r$3 === _r$3 ? _r$3 : $throwRuntimeError("integer divide by zero"));
							(x$1 = drop.glyphs, ((i < 0 || i >= x$1.$length) ? ($throwRuntimeError("index out of range"), undefined) :
								x$1.$array[x$1.$offset + i] = glyph));
						}
						row = drop.row - (i);
						r.drawGlyphAt(glyph, drop.col, row, brightness * gbrightness, i === 0);
						i = i + (1) >> 0;
					}
					_i++;
				}
				r.drops = drops;
			} catch (err) {
				$err = err;
			} finally {
				$callDeferred($deferred, $err);
			}
		};
		DigitalRain.prototype.loop = function(timestamp) {
			return this.$val.loop(timestamp);
		};
		NewGlyphCanvas = function(color) {
			var _1, _i, _ref, _rune, c, cellSize, col, color, ctx, fontSize, glyphCanvas, i, i$1, row;
			glyphCanvas = new GlyphCanvas.ptr($global.document.createElement($externalize("canvas", $String)), false);
			glyphCanvas.jso.width = 1900;
			glyphCanvas.jso.height = 500;
			ctx = glyphCanvas.jso.getContext($externalize("2d", $String));
			col = 0;
			row = 1;
			_ref =
				"glyp719813853295092+923+9hCanvas5465465465464$externalizeedsrfwetfwertfwe46545028708605116219847t986rx86854sdgf54sgdf564dfg65fds65fds56fdf56ds765658"
			_i = 0;
			while (true) {
				if (!(_i < _ref.length)) {
					break;
				}
				_rune = $decodeRune(_ref, _i);
				i = _i;
				c = _rune[0];
				if (col === 18) {
					row = row + (1) >> 0;
					col = 0;
				}
				cellSize = 100;
				fontSize = 86;
				if (i <= 36) {
					fontSize = fontSize * (0.87);
				}
				ctx.save();
				ctx.textAlign = $externalize("center", $String);
				ctx.font = $externalize(itoa(((fontSize >> 0))) + "px Monaco, Helvetica, Arial, Sans-Serif", $String);
				ctx.shadowColor = $externalize("rgba(255,255,255,0.1)", $String);
				ctx.shadowBlur = (fontSize) * 0.5;
				_1 = c;
				if ((_1 === (50)) || (_1 === (52)) || (_1 === (57))) {
					ctx.scale(-1, 1);
					ctx.translate(-(cellSize * (col) + cellSize / 2), cellSize * (row) + (fontSize - cellSize));
				} else {
					ctx.translate(cellSize * (col) + cellSize / 2, cellSize * (row) + (fontSize - cellSize));
				}
				i$1 = 0;
				while (true) {
					if (!(i$1 < 3)) {
						break;
					}
					ctx.fillStyle = $externalize(color, $String);
					ctx.fillText($externalize(($encodeRune(c)), $String), 0, 0);
					i$1 = i$1 + (1) >> 0;
				}
				ctx.restore();
				col = col + (1) >> 0;
				_i += _rune[1];
			}
			return glyphCanvas;
		};
		$pkg.NewGlyphCanvas = NewGlyphCanvas;
		GlyphCanvas.ptr.prototype.Glyph = function(gx, gy) {
			var _entry, _entry$1, _key, _key$1, ctx, gc, gx, gy, mx, my;
			gc = this;
			if (gc.glyphs === false) {
				gc.glyphs = {};
			}
			mx = (_entry = gc.glyphs[$Int.keyFor(gx)], _entry !== undefined ? _entry.v : false);
			if (mx === false) {
				mx = {};
				_key = gx;
				(gc.glyphs || $throwRuntimeError("assignment to entry in nil map"))[$Int.keyFor(_key)] = {
					k: _key,
					v: mx
				};
			}
			my = (_entry$1 = mx[$Int.keyFor(gy)], _entry$1 !== undefined ? _entry$1.v : null);
			if (my === null) {
				my = $global.document.createElement($externalize("canvas", $String));
				my.width = 100;
				my.height = 100;
				ctx = my.getContext($externalize("2d", $String));
				ctx.drawImage(gc.jso, gx, gy, 100, 100, 0, 0, 100, 100);
				_key$1 = gy;
				(mx || $throwRuntimeError("assignment to entry in nil map"))[$Int.keyFor(_key$1)] = {
					k: _key$1,
					v: my
				};
			}
			return my;
		};
		GlyphCanvas.prototype.Glyph = function(gx, gy) {
			return this.$val.Glyph(gx, gy);
		};
		ptrType$2.methods = [{
			prop: "start",
			name: "start",
			pkg: "main",
			typ: $funcType([], [$error], false)
		}, {
			prop: "layout",
			name: "layout",
			pkg: "main",
			typ: $funcType([], [], false)
		}, {
			prop: "overLink",
			name: "overLink",
			pkg: "main",
			typ: $funcType([$Int, $Int], [$Bool], false)
		}, {
			prop: "dropWaterAtCol",
			name: "dropWaterAtCol",
			pkg: "main",
			typ: $funcType([$Int, $Float64, $Int, $Float64, Duration], [], false)
		}, {
			prop: "dropRandomWaterDrop",
			name: "dropRandomWaterDrop",
			pkg: "main",
			typ: $funcType([Duration], [], false)
		}, {
			prop: "maxRows",
			name: "maxRows",
			pkg: "main",
			typ: $funcType([], [$Int], false)
		}, {
			prop: "drawGlyphAt",
			name: "drawGlyphAt",
			pkg: "main",
			typ: $funcType([$Int, $Int, $Float64, $Float64, $Bool], [], false)
		}, {
			prop: "drawGlyphElAt",
			name: "drawGlyphElAt",
			pkg: "main",
			typ: $funcType([ptrType, $Int, $Int, $Float64, $Float64], [], false)
		}, {
			prop: "drawTitle",
			name: "drawTitle",
			pkg: "main",
			typ: $funcType([$String, $String, $Float64, $Float64], [$Float64], false)
		}, {
			prop: "drawTitles",
			name: "drawTitles",
			pkg: "main",
			typ: $funcType([], [], false)
		}, {
			prop: "loop",
			name: "loop",
			pkg: "main",
			typ: $funcType([Duration], [], false)
		}];
		ptrType.methods = [{
			prop: "Glyph",
			name: "Glyph",
			pkg: "",
			typ: $funcType([$Int, $Int], [ptrType$3], false)
		}];
		DigitalRain.init("main", [{
			prop: "parent",
			name: "parent",
			anonymous: false,
			exported: false,
			typ: ptrType$3,
			tag: ""
		}, {
			prop: "canvas",
			name: "canvas",
			anonymous: false,
			exported: false,
			typ: ptrType$3,
			tag: ""
		}, {
			prop: "ctx",
			name: "ctx",
			anonymous: false,
			exported: false,
			typ: ptrType$3,
			tag: ""
		}, {
			prop: "width",
			name: "width",
			anonymous: false,
			exported: false,
			typ: $Float64,
			tag: ""
		}, {
			prop: "height",
			name: "height",
			anonymous: false,
			exported: false,
			typ: $Float64,
			tag: ""
		}, {
			prop: "ratio",
			name: "ratio",
			anonymous: false,
			exported: false,
			typ: $Float64,
			tag: ""
		}, {
			prop: "timestamp",
			name: "timestamp",
			anonymous: false,
			exported: false,
			typ: Duration,
			tag: ""
		}, {
			prop: "lowGlyphCanvas",
			name: "lowGlyphCanvas",
			anonymous: false,
			exported: false,
			typ: ptrType,
			tag: ""
		}, {
			prop: "highGlyphCanvas",
			name: "highGlyphCanvas",
			anonymous: false,
			exported: false,
			typ: ptrType,
			tag: ""
		}, {
			prop: "drops",
			name: "drops",
			anonymous: false,
			exported: false,
			typ: sliceType$2,
			tag: ""
		}, {
			prop: "linkover",
			name: "linkover",
			anonymous: false,
			exported: false,
			typ: $Bool,
			tag: ""
		}, {
			prop: "screenCols",
			name: "screenCols",
			anonymous: false,
			exported: false,
			typ: $Int,
			tag: ""
		}, {
			prop: "minSpeed",
			name: "minSpeed",
			anonymous: false,
			exported: false,
			typ: $Int,
			tag: ""
		}, {
			prop: "maxSpeed",
			name: "maxSpeed",
			anonymous: false,
			exported: false,
			typ: $Int,
			tag: ""
		}, {
			prop: "brightness",
			name: "brightness",
			anonymous: false,
			exported: false,
			typ: $Float64,
			tag: ""
		}, {
			prop: "Clicked",
			name: "Clicked",
			anonymous: false,
			exported: true,
			typ: funcType,
			tag: ""
		}]);
		waterDrop.init("main", [{
			prop: "col",
			name: "col",
			anonymous: false,
			exported: false,
			typ: $Int,
			tag: ""
		}, {
			prop: "row",
			name: "row",
			anonymous: false,
			exported: false,
			typ: $Float64,
			tag: ""
		}, {
			prop: "start",
			name: "start",
			anonymous: false,
			exported: false,
			typ: $Float64,
			tag: ""
		}, {
			prop: "speed",
			name: "speed",
			anonymous: false,
			exported: false,
			typ: $Float64,
			tag: ""
		}, {
			prop: "glyphs",
			name: "glyphs",
			anonymous: false,
			exported: false,
			typ: sliceType$3,
			tag: ""
		}, {
			prop: "spedup",
			name: "spedup",
			anonymous: false,
			exported: false,
			typ: $Bool,
			tag: ""
		}, {
			prop: "created",
			name: "created",
			anonymous: false,
			exported: false,
			typ: Duration,
			tag: ""
		}]);
		GlyphCanvas.init("main", [{
			prop: "jso",
			name: "jso",
			anonymous: false,
			exported: false,
			typ: ptrType$3,
			tag: ""
		}, {
			prop: "glyphs",
			name: "glyphs",
			anonymous: false,
			exported: false,
			typ: mapType$1,
			tag: ""
		}]);
		$init = function() {
			$pkg.$init = function() {};
			var $f, $c = false,
				$s = 0,
				$r;
			if (this !== undefined && this.$blk !== undefined) {
				$f = this;
				$c = true;
				$s = $f.$s;
				$r = $f.$r;
			}
			s: while (true) {
				switch ($s) {
					case 0:
						$r = js.$init();
						$s = 1;
					case 1:
						if ($c) {
							$c = false;
							$r = $r.$blk();
						}
						if ($r && $r.$blk !== undefined) {
							break s;
						}
						lowGlyphCanvases = sliceType.nil;
						highGlyphCanvases = sliceType.nil;
						backgrounds = sliceType$1.nil;
						overlap = 0;
						githubLinkColor = "rgba(107,165,184,.5)";
						githubLinkOverColor = "rgba(107,165,184,1)";
						githubLink = "";
						level1Cols = 40;
						level2Cols = 60;
						index = 1;
						if ($pkg === $mainPkg) {
							main();
							$mainFinished = true;
						}
				}
				return;
			}
			if ($f === undefined) {
				$f = {
					$blk: $init
				};
			}
			$f.$s = $s;
			$f.$r = $r;
			return $f;
		};
		$pkg.$init = $init;
		return $pkg;
	})();
	$synthesizeMethods();
	var $mainPkg = $packages["main"];
	$packages["runtime"].$init();
	$go($mainPkg.$init, []);
	$flushConsole();
}).call(this);
